<<

Adopting the Noise exchange in

Integration des Noise Schlüsselaustauschprotokolls in Tox

Master Thesis

Submitted in partial fulfillment of the requirements for the degree of

Master of Science in Engineering

to the University of Applied Sciences FH Campus Wien Master Degree Program: IT-Security

Author: Tobias Buchberger

Student identification number: c1810537022

Supervisor: DI Mathias Tausig

Date: 04.07.2020 Declaration of authorship:

I declare that this Master Thesis has been written by myself. I have not used any other than the listed sources, nor have I received any unauthorized help.

I hereby certify that I have not submitted this Master Thesis in any form (to a reviewer for assessment) either in Austria or abroad.

Furthermore, I assure that the (printed and electronic) copies I have submitted are iden- tical.

Date: Signature: Preface

First of all I would like to take the time to thank my supervisor, Mathias Tausig, for all the help. You were the one who inspired me to choose this topic which combined my already- existing interest in Tox and . During the practical part of this thesis you guided me in the right directions and in our regular feedback sessions you always encouraged me. Moreover I want to thank zoff, iphy, zugz and nurupo from TokTok (Tox’ development organization) for valuable discussions and help in understanding Tox and its implementation. I look forward to further improve Tox together with these interesting people. Beer’s on me at the next ToxCon! ;-) I also want to thank Jason A. Donenfeld for intially raising the KCI issue in Tox’ handshake. Last but not least I want to thank my partner Hannah for all her help and endurance during the ups and downs while working on this thesis. She always kept calm and managed not to break up with me ;-).

i Abstract

Tox is a peer-to-peer protocol that aims to provide . The development of Tox started in the wake of ’s leaks regarding the US National Security Agencies’ (NSA) of most communications. It’s in- tended as a end-to-end encrypted (E2EE) and distributed replacement. Tox features include instant messaging, audio and video calls. The implementation of the Tox protocol is written in and the library is called "c-toxcore". Tox’ cryptography is based on the NaCl library from Daniel J. Bernstein. The cryptographic primitives for the (X25519), () and symmetric (XSalsa20) are state of the art peer-reviewed algorithms. Although Tox’ authenticated key exchange (AKE) during the handshake works, it is a "home-brewed" cryptographic protocol. Until now there was no full security analysis conducted on either the Tox protocol or its implementation in C, but the AKE is known to be vulnerable to key compromise impersonation (KCI) attacks. KCI is a vulnerability of AKE protocols, which in this case enables an attacker, who compromised the static long-term private X25519 key of a Tox party Alice, to impersonate any other Tox party (with certain qualifications) to Alice ("reverse impersonation"). This enables an attacker to perform a Man-in-the-Middle (MitM) attack. The cryptographic handshake of the Tox pro- tocol, including the AKE, is described in detail. Based on the analysis of the Tox handshake multiple KCI-attack scenarios are outlined. The Noise Protocol Framework (hereafter referred to as "Noise") is a framework created by Trevor Perrin intended to use by protocol designers to create secure channel protocols based on Diffie-Hellman key agreement. Noise provides different handshake patterns for different use cases. The security properties of these patterns are formally verified. These security properties can include , key confirmation, identity hiding and most notably KCI-resistance. Noise protocols are already used in some applications, like WireGuard VPN and WhatsApp. By using the Noise framework, a new KCI-resistant AKE for the Tox handshake is designed. Tox’ Noised-based AKE uses the "IK" pattern. The name of the resulting Noise protocol is Noise_IK_25519_ChaChaPoly_SHA512. This means the new AKE is also based on X25519 for the key exchange, but encryption during the AKE is performed using the ChaCha20-Poly1305 stream cipher instead of XSalsa20 (which is not supported by Noise). The Noise-C library from Rhys Weatherley is used to implement the new AKE in c-toxcore. Two functions are added to Noise-C to be able to retrieve to the symmetric encryption keys after a successful handshake. These keys are then used with the already-existing XSalsa20-Poly1305 encryption in c-toxcore to send encrypted . In future work, instead of using the Noise-C library, which supports most of Noise’ hand- shake patterns and all cryptographic primitives, only the Noise protocol used in the Tox handshake can be implemented in c-toxcore. This would remove Noise-C as a dependency (i.e the only other dependency is NaCl/libsodium), reduce source lines of code and therefore reduce the attack surface. Noise also provides functions to further improve security, like ses- sion re-keying, which could also be adopted in Tox. Future work could also include further security analysis of the Tox protocol and its implementation in C.

ii Kurzfassung

Tox ist ein Peer-to-Peer Instant-Messaging Protokoll, das zum Ziel hat sichere Kommu- nikation zu ermöglichen. Die Entwicklung von Tox hat im Anschluss an Edward Snowdens Veröffentlichungen hinsichtlich der Überwachung der internetbasierten Kommunikation durch die US (NSA) begonnen. Es ist als Ende-zu-Ende verschlüsselte und verteilte Alternative zu Skype gedacht. Tox ermöglicht unter anderem Instant-Messaging und Sprach- bzw. Videotelefonie. Das Tox-Protokoll ist in C implementiert und die Pro- grammbibliothek heißt „c-toxcore“. Die in Tox verwendete Kryptographie basiert auf der NaCl-Programmbibliothek von Daniel J. Bernstein. Die kryptographischen Verfahren für den Schlüsselaustausch (X25519), die Authentifizierung (Poly1305) und die symmetrische Verschlüsselung (XSalsa20) sind aktueller Stand der Technik. Tox’ authentifizierter Schlüs- selaustausch während des Handshakes funktioniert, ist aber ein selbsterstelltes kryptographis- ches Protokoll. Bisher wurde noch keine vollständige Sicherheitsanalyse des Tox-Protokolls oder der Implementierung in C durchgeführt. Es ist jedoch bekannt, dass der Schlüsselaus- tausch für "Key Compromise Impersonation"-Angriffe (KCI) anfällig ist. Im Fall von Tox kann dies einem Angreifer, der den privaten Langzeit-X25519-Schlüssel einer Tox-Benutzerin Alice kompromittiert hat, unter bestimmten Voraussetzungen ermöglichen, sich gegenüber Alice als beliebiger Tox-Benutzer auszugeben. Dies befähigt einen Angreifer Man-in-the- Middle-Attacken durchzuführen. Der kryptographische Handshake des Tox-Protokolls, ein- schließlich des Schlüsselaustausches, wird im Detail beschrieben. Basierend auf der Analyse des Handshakes werden mehrere KCI-Angriffs-Szenarien erläutert. Das Noise Protocol Framework (Noise) wurde von Trevor Perrin entworfen und ist dazu gedacht, von Entwicklern für den Entwurf von Protokollen zum Aufbau sicherer Kommu- nikationskanäle basierend auf dem Diffie-Hellman-Schlüsselaustausch, verwendet zu werden. Noise stellt sogenannte Handshake-Patterns für unterschiedliche Anwendungsfälle zur Ver- fügung. Die Sicherheits-Eigenschaften dieser Patterns sind formal verifziert und sind unter anderem Forward Secrecy, glaubhafte Abstreitbarkeit und am Wichtigsten Resistenz gegen KCI. Noise-Protokolle werden bereits in einigen Applikationen eingesetzt, wie z.B. - Guard VPN und WhatsApp. Mit der Anwendung von Noise wird ein neuer Schlüsselaus- tausch mit Resistenz gegen KCI für das Tox-Protokoll konzipiert. Der Noise-basierte Schlüs- selaustausch verwendet das "IK" Pattern. Der Name des resultierenden Noise-Protokolls ist Noise_IK_25519_ChaChaPoly_SHA512. Daher basiert auch der neue Schlüsselaustausch auf X25519, aber die Verschlüsselung während dem Schlüsselaustausch wird anstelle von XSalsa20 (welches von Noise nicht unterstützt wird) mit ChaCha20 durchgeführt. Die Noise- C Programmbibliothek von Rhys Weatherley wird verwendet, um den neuen Schlüsselaus- tausch in c-toxcore umzusetzen. Zwei Funktionen werden zu Noise-C hinzugefügt, um die Schlüssel für symmetrische Verschlüsselung nach einem erfolgreichen Handshake abzufra- gen. Diese Schlüssel werden anschließend mit der bereits existierenden XSalsa20-Poly1305- Verschlüsselung verwendet, um Nachrichten zu senden. Als nächster Schritt ist angedacht das in Tox verwendete Noise-Protokoll explizit für Tox zu entwickeln, anstatt die Noise-C Programmbibliothek zu verwenden, die die meis- ten Noise-Handshake-Patterns und kryptographischen Verfahren unterstützt. Dies würde die Abhängigkeit von Noise-C für c-toxcore entfernen und durch eine reduzierte Anzahl von Quellcodezeilen die Angriffsoberfläche verringern. Außerdem stellt Noise weitere Funktionen, wie z.B. Session-Rekeying, zur Verfügung, die in Tox übernommen werden könnten, um die Kommunikationssicherheit weiter zu erhöhen. Ebenfalls könnte für das Tox-Protokoll und seine Implementierung in C eine tiefgehende Sicherheitsanalyse durchgeführt werden.

iii List of Abbreviations

ACCE Authenticated and Confidential Channel Establishment AEAD with Associated Data AES Advanced Encryption Standard AKE Authenticated Key Exchange ATHiCC Asynchronous Hidden Chat Communication DAKE Deniable Authenticated Key Exchange DH Diffie-Hellman DHT DoS Denial of Service E2EE End-to-End Encryption ECDH Elliptic-Curve Diffie-Hellmann FLOSS Free/Libre Software GCHQ Government Communications Headquarters GPL GNU General Public License Invisible Internet Project IETF Internet Engineering Task Force IM Instant Messaging IPSec Internet Protocol Security KCI Key Compromise Impersonation KDF Key Derivation Function MAC Message Authentication Code MitM Man-in-the-Middle MLS Messaging Layer Security MQV Menezes-Qu-Vanstone NaCl Networking and Cryptography library Noise Noise Protocol Framework NSA National Security Agency P2P Peer-to-Peer PoC Proof-of-Concept RTT Round-Trip Time SCP Secure Channel Protocol SSH Secure Shell TLS VPN

iv Key Terms

AKE Authenticated Key Exchange KCI Key Compromise Impersonation E2EE End-to-End Encryption Noise Protocol Framework Secure Messaging Tox X25519

v Contents

1. Introduction1 1.1. Motivation and Contribution ...... 2 1.2. Related Work ...... 3 1.3. Structure of this Thesis ...... 5

2. Background 6 2.1. ...... 6 2.2. Authenticated Key Exchange and Secure Channels ...... 7 2.3. Tox...... 13 2.4. Current Cryptographic Handshake and AKE in Tox ...... 18 2.5. Noise Protocol Framework ...... 25

3. Key Compromise Impersonation and Tox 31 3.1. Key Compromise Impersonation ...... 31 3.2. KCI-Vulnerability in Tox’ AKE ...... 32 3.3. Prerequisites for a KCI-Attack on Tox ...... 33 3.4. M impersonates B to A using KCI ...... 34 3.5. Active MitM Attack based on KCI ...... 36 3.6. KCI-Attack with DHT Keys ...... 40

4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise 42 4.1. Design of a KCI-resistant Tox Handshake based on the Noise IK Pattern . . . 42 4.2. Implementation Overview of the Noise IK based Tox Handshake ...... 48 4.3. Implementation Approach with ChaCha20-Poly1305 during the AKE and the Transport Phase ...... 54 4.4. Final Implementation with Chacha20-Poly1305 during the AKE and XSalsa20- Poly1305 during the Transport Phase ...... 62

5. Conclusion and Future Work 70 5.1. Future Work ...... 71

Bibliography 73

List of Figures 79

List of Tables 80

Listings 81

Lists 82

A. Appendix 83 A.1. Tox protocol packets ...... 83 A.2. Implementation ...... 84

vi A.3. Building libsodium ...... 85 A.4. Building Noise-C ...... 85 A.5. Building c-toxcore ...... 86

vii 1. Introduction

Nowadays instant messaging (IM) has grown to one of the most relevant means of communi- cation. WhatsApp for instance had about 500 million daily active users in the first quarter of 2019 [Cle19] and more than 2 billion in total in February 2020 [Wha20]. The messages and files (e.g. pictures, audio, video and documents) exchanged via these services can be very sensitive. for users of these services needs to be retained. Otherwise users’ sensi- tive information can be collected and analyzed by companies and authorities like intelligence agencies. In June 2013 media outlets started to report worldwide of most internet communications conducted by the US National Security Agency (NSA) and other western in- telligence agencies [Wil13, Gre13, Hei13]. These reports were made possible by whistleblower Edward Snowden, who worked for the NSA [PG13]. According to a surveillance program called PRISM started in 2007. This program was established to collect internet communications from various US internet companies including Facebook, Skype and Apple [Wil13]. Most of these companies offer their own closed source IM services, like Face- book’s WhatsApp and Microsoft’s Skype. Some of these IM providers also spy on their users. Skype for instance "will process your personal information, the traffic data and the content of your communication(s) in accordance with our Privacy Policy" [Mic19a, Mic19b]. These revelations by Edward Snowden regarding government surveillance have highlighted the lack of secure messaging tools. In response to increased public awareness and subsequent demand, new messaging applications claiming to provide security and privacy were released. Among others, the and Tox protocols were designed and implemented. A few years later, the (based on X3DH key agreement [MP16], Double Ratchet [PM16], XEdDSA/VXEdDSA [Per16] and Sesame [MP17]), which was developed by Moxie Marlin- spike and Trevor Perrin, is the de facto standard for secure communications (cf. [EM19]). Ermoshina and Musiani call this "standardisation by running code" [EM19]. WhatsApp, the global market leader, adopted the Signal protocol to provide end-to-end encryption (E2EE) for all its users [Mar16b]. By using WhatsApp or Signal ordinary citizens’ communications are protected. Therefore secure messaging is not limited to privacy advocates and cryptog- raphers. However, there are also users that do care about sources of funding and business models of end-to-end encrypted messaging applications. Critiques addressed to Signal concern their dependency on US government funding. Signal received around $2.3 million from the [Gre16]. According to Yasha Levine, this Open Technology Fund works closely with the US State Department [Lev16]. Marlinspike declines to publicly name other wealthy Signal donors [Gre16]. Also, Signal requires that users tie their app to a real number (which is then also their Signal identity) and give unrestricted access to their entire address book. Further, centralization per se has become a controversy. It is promoted by Marlinspike as a better governance option for secure . Marlinspike argues that "once you federate your protocol, it becomes very difficult to make changes" [Mar16a]. They also state that "it’s entirely possible to build a federated Signal Protocol-based messenger, but I no longer

1 Chapter 1. Introduction believe that it is possible to build a competitive federated messenger at all" [Mar16a]. In Contrast, Matthew Hodgson, the technical co-founder of , argues that "to declare that openness, interoperability and decentralisation is ’too hard’ and not worth the effort when building a messaging solution is to throw away all the potential of the vibrancy, creativity and innovation that comes from an open network" [Hod20].

1.1. Motivation and Contribution

For users, that want to communicate end-to-end encrypted and at the same time don’t want to rely on big corporations which provide centralized messaging services (like Facebook which owns WhatsApp), Tox is an example for a free/libre and open source software (FLOSS) alter- native licensed under the GNU General Public License version 3 (GPLv3). Instead of using central severs, the Tox protocol creates secure channels directly between two communication partners. Unfortunately many new messaging tools repeat known design mistakes or use cryptography in insecure ways. This is also the case with Tox. Tox is a messenger protocol based on a cryptographic network library implemented by Daniel J. Bernstein, called NaCl (pronounced "salt"). This means the primitives for the key exchange (X25519 [Ber06]), au- thentication (Poly1305 [Ber05]) and symmetric encryption (XSalsa20 [Ber11]) are state of the art peer-reviewed cryptographic algorithms [Tok20]. However, the key exchange (during a Tox handshake) itself is a simple transfer of ephemeral public keys encrypted with static long-term public keys (that also serve as user IDs), authenticated with the long-term private keys. This method of key exchange works, but is known to be vulnerable to Key Compromise Impersonation (KCI) [Don17a]. Trevor Perrin’s Noise Protocol Framework is a formally-verified authenticated key exchange (AKE) construction which was designed to protect against KCI. [Per18, Gir19, KNB19] By using a so-called Noise protocol, which provides the necessary security properties, it is pos- sible to design and implement an authenticated key exchange protocol which provides KCI- resistance. The goal of this thesis is to demonstrate the KCI-attack on Tox, implement a new KCI- resilient cryptographic handshake in Tox (more precisely in the toxcore library) by using a proper Noise protocol and show that the resulting key exchange is KCI-resistant. The primary contributions of this thesis are: • A detailed description of Tox’ handshake (including the KCI-vulnerable AKE) • A detailed explanation why Tox’ handshake is vulnerable to KCI • Presentation of necessary prerequisites to carry out a KCI-attack • Demonstration of different KCI-attack scenarios on Tox’ handshake • Design of a new KCI-resistant AKE in the Tox handshake by using a Noise protocol • Implementation and testing of this new Noise-based handshake in toxcore

2 Chapter 1. Introduction

1.2. Related Work

This section discusses related work of this thesis. Note that the following paragraphs mention contents that will be outlined in more detail in later chapters.

1.2.1. Tox

At the moment of writing this thesis there is no known research on the implementation of a Noise protocol in a P2P chat protocol like Tox. The identified related work outlined below involves Tox in other contexts than this thesis. These papers use Tox as a basis to implement something on top (cf. [Har15]) or outline the (security) features of Tox to compare them to other instant-messengers (cf. [Jel16, Vog16]). Tamino Hartmann of the Ulm University wrote his master thesis on "Tizenite: Encrypted Peer to Peer File Synchronization via the Tox Protocol". In their thesis they proposed and implemented an open source, P2P, file synchronization software based on the Tox protocol. [Har15] Alexander Jelinek of FH Campus Wien wrote his bachelor thesis on "Security aspects of secure messaging". In his thesis an ideal of the secure instant-messenger is outlined. Three instant-messengers are compared with the presented ideal instant-messenger, including Tox. [Jel16] Markus Vogl of Johannes Kepler University Linz performed an extensive evaluation on the secure instant messaging landscape. The paper covers a wide range of instant-messengers including WhatsApp, Signal and Tox. It lists and compares their security features, privacy aspects and other information. [Vog16]

1.2.2. Secure Instant Messaging

Unger et al. provide a comprehensive systemization of knowledge on secure messaging. In their paper they evaluate and systematize current secure messaging solutions. They further propose an evaluation framework for their security, usability and ease-of-adoption properties. They considered solutions from academia, but also innovative and promising approaches that are not considered by academic literature. Unger et al. identified three key challenges: trust establishment, conversation security and transport privacy. [UDB+15] Nik Unger also wrote his thesis "Deniable Key Exchanges for Secure Messaging" [Ung15] and published a paper with the same name together with [UG15]. In this thesis they provide a guide for practitioners seeking to implement deniable secure messag- ing systems. Unger constructed several new practical deniable authenticated key exchanges (DAKEs) with the intention of providing deniability in modern secure messaging environ- ments. One of the proposed DAKEs, namely Spawn, is the first non-interactive DAKE that offers forward secrecy and achieves deniability against both offline and online judges. [Ung15] Further Unger and Goldberg published a paper on "Improved Strongly Deniable Authen- ticated Key Exchanges for Secure Messaging". In this work three new strongly deniable key exchange protocols are proposed, namely DAKEZ, ZDH and XZDH. These are designed to be used in modern secure messaging applications and eliminate the weaknesses of previous ap- proaches. Complete algebraic specifications, recommendations and prototype implementations are included for these three DAKEs. [UG18] Balchasan et al. present a novel protocol called ATHiCC (Asynchronous Tor Hidden Chat Communication), that allows private and anonymous communication that doesn’t require

3 Chapter 1. Introduction a and supports asynchronous communication [BOS+19]. This may sound interesting to adopt in Tox in order to support asynchronous messaging, but ATHiCC doesn’t support UDP (only TCP). Not explicitly relevant for this thesis, but interesting to mention is that a lot of work is currently put in the research of secure group messaging. Schliep and Hopper proposed "Mobile CoWPI", a deployable, end-to-end secure mobile group messaging application with proofs of security [SH19]. Chase et al. [CPZ19] are working on a system for maintaining a membership list of users in a group, designed for use in the Signal messenger. In their proposed solution, a central server stores the group membership in the form of encrypted entries [CPZ19]. A working group of the Internet Engineering Task Force (IETF) is currently working on a Messaging Layer Security (MLS) protocol standard (cf. Transport Layer Security (TLS)). The focus of MLS is to improve the scalability of E2EE to support thousands of users in a group while explicitly not supporting conversation integrity or deniability [BMO+20].

1.2.3. AKE and KCI

There is different research conducted on Diffie-Hellman (DH) based key agreement protocols that are proven to provide KCI-resistance, e.g. HMQV from Hugo Krawczyk [Kra05] and NAXOS from LaMacchia et al. [LLM07]. In 2006 Strangio analyzed a few key agreement protocols and showed that these are vulnerable to KCI-attacks [Str06]. In 2007 Strangio presented the ECKE-1R protocol, a revised version of ECKE-1 that is KCI-resilient [Str07]. Hlauschek et al. discovered that the TLS protocol includes key agreement and authenti- cation methods that are vulnerable to KCI-attacks: non-ephemeral DH key exchange with fixed DH authentication on both elliptic curve groups and on integer groups modulo a prime. They show that TLS clients that support these weak handshakes are vulnerable to Man-in-the-Middle (MitM) attacks based on KCI. Further Hlauschek et al. present a suc- cessful MitM attack against the Safari web browser on macOS by exploiting KCI in TLS. [HGFS15]

1.2.4. Noise Protocol Framework

Noise protocols are already in use in some applications. In 2017 Jason A. Donenfeld presented WireGuard, a secure network tunnel operating at layer 3, which uses the Noise IK pattern in a single round trip key exchange to establish secure connections [Don17b]. Also in 2017 Donenfeld and Milner enumerated the security properties of WireGuards Noise-based key exchange and performed a formal verification of those properties [DM17]. Therefore Wire- Guard is a formally-verified secure network tunnel protocol based on Noise. In 2018 Dowling and Paterson conducted a cryptographic analysis of the WireGuard protocol [DP18]. They observed that in order to prevent KCI-attacks the first AEAD encrypted message from ini- tiator to responder must be taken into account. This message acts as a key confirmation and makes the AKE of WireGuard actually a 1.5 roundtrip-time (RTT) protocol. In 2019 Peter Wu published his master thesis on the WireGuard protocol including an extensive analysis [Wu19]. The Invisible Internet Project (I2P) used the Noise Protocol Framework to design and implement the NTCP2 AKE protocol. NTCP2 is based on the Noise XK handshake pattern with a few enhancements to the used Noise protocol (e.g. cleartext ephemeral keys are obfuscated with AES encryption). [vil18]

4 Chapter 1. Introduction

In 2019 Hall-Andersen et al. presented nQUIC a variant of QUIC-TLS that uses the Noise protocol framework for its key exchange. [HAWSC18] The formal verification of Noise handshake pattern security is discussed separately in sec- tion 2.5.4.

1.3. Structure of this Thesis

The remainder of this thesis is structured as follows. Chapter 2 gives an overview in regard to secure instant messaging, Tox and the Noise Protocol Framework. It further describes the purpose and properties of authenticated key exchange protocols that are used to create secure channels. This chapter also explains Tox cryptographic handshake in detail, including the vulnerable key exchange. Chapter 3 describes KCI in general and Tox’ KCI-vulnerability in particular. The prereq- uisites for a KCI-attack on Tox and multiple attack scenarios based on these prerequisites are presented. Chapter 4 includes the design and implementation of a KCI-resistant Tox handshake based on a Noise protocol. Chapter 5 concludes this thesis and outlines possible future work.

5 2. Background

This chapter gives a short overview on secure instant messaging. It also discusses authenti- cated key exchanges, important properties AKE protocols can provide in respect to secure messaging, (elliptic-curve) Diffie-Hellman (ECDH) and how an AKE protocol is used to cre- ate a secure communications channel. Furthermore this chapter takes a closer look at Tox, the goals of the Tox protocol, how it is structured and what cryptographic primitives it is based on. Afterwards Tox’ handshake, including the custom AKE, is described in detail. This chapter concludes with an introduction to the Noise protocol framework.

2.1. Secure Instant Messaging

There are many instant messaging services available to the public. They are built on three different types of underlying architectures (cf. figure 2.1): centralized (e.g. WhatsApp1, Signal2), decentralized/federated (e.g. XMPP3, Matrix4) and distributed/peer-to-peer (e.g. Tox5).

Figure 2.1.: Illustration of centralized, decentralized and distributed networks (cf. [BOS+19])

Centralized chat systems rely on a single entity for decision making, such as a server. This means that this one entity (which could also be a group of entities acting as one) provides a critical service for the function of the chat system. They are easy to maintain and manage, and provide control over the system. [BOS+19] Signal for instance requires central servers to relay encrypted messages and store public key material [Sig19].

1https://www.whatsapp.com 2https://signal.org/ 3https://xmpp.org/ 4https://matrix.org/ 5https://tox.chat/

6 Chapter 2. Background

Decentralized chat systems are systems where a subset of the entities provides services and decision making to the rest of the network. These service-providing entities operate indepen- dently of each other. [BOS+19] Matrix is an example for a decentralized (federated) protocol but most of its users use the same server (i.e. matrix.org). The matrix.org homeserver cur- rently makes up about 35% of the visible Matrix network by active users [Hod20]. This server was recently hacked and users (may have) lost access to their encrypted messages [Mat19]. Distributed or peer-to-peer (P2P) chat systems are systems where all entities are equal. There are no nodes who are more "important" than others. Decision making is performed on the individual level. [BOS+19] This is not entirely true for Tox because it requires so- called bootstrap nodes to enter the distributed network. P2P based systems establish a direct connection to exchange messages between participants. These systems often use distributed hash tables (DHTs) to map usernames to IP addresses without relying on a central author- ity because end users regularly change their IP addresses [UDB+15]. It is also possible to provide P2P IM without the internet and IP addresses by directly exchanging messages over mesh networks via or WiFi. An example for a messenger providing such functionality is Briar6. Another aspect of secure IM are the two the different types of messaging, asynchronous and synchronous. Asynchronous messaging does not require participants to be online when messages are sent, utilizing a third party (e.g. a central server) to cache messages for later delivery. Synchronous messaging requires all participants to be online and connected at the same time in order for messages to be transmitted. Chat systems with a peer-to-peer architecture, where the sender directly connects to the recipient for message transmission, are examples of synchronous protocols. Therefore Tox provides only synchronous messaging. Besides Tox, most popular instant messaging solutions today provide asynchronicity by using a store-and-forward model: a central server is used to buffer messages when the recipient is offline. [BOS+19, UDB+15] For an extensive evaluation and systemization of current secure messaging solutions see [UDB+15]. Unger et al. identified three key challenges and map the design landscape for each: trust establishment (i.e. ensuring the distribution of cryptographic long-term keys and proof of association with the owning entity), conversation security (i.e. ensuring the protection of exchanged messages during conversations) and transport privacy (i.e. hiding the communication metadata). For each problem area Unger et al. identify desirable properties divided into three main groups: security and privacy features, usability features, and adoption considerations. They also proposed an evaluation framework for the security, usability and ease-of-adoption properties of messaging solutions. [UDB+15]

2.2. Authenticated Key Exchange and Secure Channels

In this thesis the term (authenticated) key exchange (also key establishment or key agreement protocol) is used for protocols that involve setting up a new shared key, typically for a communications session. In order for two parties to communicate securely over an untrusted public network, they must be able to authenticate one another and agree on a secret encryption key. To achieve this, key establishment protocols are used at the start of a communication session to verify both parties identities and to agree on a session key. There are different types of key establishment protocols. In key transport protocols the key is created by one party and securely transmitted

6https://briarproject.org/

7 Chapter 2. Background to the second party. In key agreement protocols both parties contribute information which is used to derive the key. Further key establishment protocols can be symmetric or asymmetric. In symmetric protocols the two parties possess common secret information beforehand, while in asymmetric protocols the two parties share only public information that has been authenticated. [BWM98] This thesis is concerned with two-party authenticated key agreement/exchange protocols in the asymmetric setting. Menezes et al. define key agreement protocols as follows [MVOV96]: A key agreement protocol or mechanism is a key establishment technique in which a shared secret is derived by two (or more) parties as a function of information contributed by, or associated with, each of these (ideally) such that no party can predetermine the resulting value. In an AKE such as authenticated DH, both communication parties generate an ephemeral session key and authenticate the exchange using their long-term keys. The resulting DH-based session key is used to derive symmetric encryption and message authentication code (MAC) keys, which then protect messages using an encrypt-then-MAC approach. This provides confidentiality, integrity and authentication for this communication session. [UDB+15]

2.2.1. Properties of Authenticated Key Exchange Protocols

Any attack on a protocol is only valid if it violates a property that the protocol intended to provide. Hence all attacks must be considered relative to the protocol goals. Many Protocol problems emerge when designers are unclear about the protocols goals they are trying to achieve. This also leads to disputes about whether attacks on a protocol are valid, since designers may regard the goals differently from analysers. [BMS20] In this section the properties of AKE protocols that deemed to be relevant for this thesis (i.e. in regard to secure messaging and Tox) are described.

Entity Authentication

Menezes et al. define entity authentication as follows [MVOV96]: Entity authentication is the process whereby one party is assured (through acqui- sition of corroborative evidence) of the identity of a second party involved in a protocol, and that the second has actually participated (i.e. is active at, or imme- diately prior to, the time the evidence is acquired). Entity authentication is a service that is provided by one entity to another entity (or more other entities). For an interaction between two entities it may be desirable if both provide authentication to one another ("mutual authentication"). [BMS20] Boyd et al. define mutual authentication as follows [BMS20]: Mutual authentication occurs if both entities are authenticated to each other in the same protocol. Unilateral authentication (sometimes called one-way authenti- cation) occurs if only one entity is authenticated to the other.

8 Chapter 2. Background

Key Confirmation

Boyd et al. define key confirmation as follows [BMS20]: Key confirmation of B to A is provided if A has assurance that key K is a good key to communicate with B, and that principal B has possession of K. Key confirmation is typically achieved by having both communication parties send each other some fresh data using a cryptographic function depending on the key. This is often referred to as a handshake. [BMS20]

Forward and Backward Secrecy

An AKE protocol provides forward secrecy if a compromised long-term key doesn’t enable an adversary to decrypt ciphertexts that were encrypted with previous session keys (see figure 2.2a) [UDB+15]. Forward secrecy is provided in key agreement protocols in which the long-term key is only used to authenticate the exchange [BMS20]. Boyd et al. define forward secrecy as follows [BMS20]: A key establishment protocol provides forward secrecy if compromise of the long- term keys of a set of principals does not compromise the session keys established in previous protocol runs involving those principals. Boyd et al. define weak forward secrecy as follows [BMS20]: A protocol provides weak forward secrecy if compromise of the long-term keys of one or more specific principals does not compromise the session keys established in previous protocol runs involving those principals when the adversary did not take an active part in the session under attack. If the compromise of a long-term key does not allow subsequent ciphertexts to be decrypted by passive adversaries, then a protocol is said to provide backward secrecy (see figure 2.2b). However, protocols with backward secrecy are still vulnerable to active attackers that are in possession of long-term keys. [UDB+15]

Figure 2.2.: Session keys are protected from long-term key compromise (cf. [UDB+15])

Key Compromise Impersonation

When an adversary learns the long-term key of party A this adversary can impersonate A to other parties until the compromise is detected and the long-term key is revoked. Key

9 Chapter 2. Background compromise impersonation enables an attack in which the adversary uses A’s compromised long-term key to masquerade to A as another party. [BMS20] Chapter 3 discusses KCI in detail.

Deniability

Deniability, also called repudiability, is a privacy property of a key establishment protocol that is desirable in certain circumstances. The idea is that users of a deniability-providing protocol can deny taking part in a communication session. Communications without any cryptographic mechanism can always be denied. However it may be desirable to provide authentication to the receiving party and to set up a secure channel to protect the confidentiality and integrity of the information being exchanged. [BMS20, UDB+15] Unger et al. refer to this kind of deniability as participant repudiation. Further, they also discuss two additional deniability properties, namely message repudiation and message un- linkability. Message repudiation is implied by participant repudiation and allows participants to deny sending of a specific message. Message unlinkability is a property that if a third person can be convinced a user authored one message, this should not prove the authorship of any other message. [UDB+15]

2.2.2. (Elliptic-Curve) Diffie-Hellman

DH key agreement was publicly introduced by Whitfield Diffie and Martin Hellman in 1976 [DH76]. This non-secret encryption was already known to the British intelligence agency Gov- ernment Communications Headquarters (GCHQ) in 1974 because Malcolm J. Williamson, an employee from GCHQ, was simuntaneously working on public key cryptography [Wil74]. This was unknown to the public until the documents were declassified by the British government. DH is the basis for a vast range of protocols, but on its own lacks any authentication. In the basic DH protocol, two parties A and B agree publicly on an g that gen- erates a multiplicative group G. They then select random values rA and rB, in the range r r between 1 and the order of G. A calculates tA = g A and B calculates tB = g B . A sends tA to B and B sends tB to A. Now both of them can calculate the same shared secret rArB rB rA Z = g = tA = tB (see figure 2.3). [BMS20]

Shared information: Generator g of G AB

rA ←$ Zq rA tA ← g

tA

rB ←$ Zq rB tB ← g

tB

rA rB Z ← tB Z ← tA

Figure 2.3.: Diffie-Hellman key agreement (cf. [BMS20])

10 Chapter 2. Background

∗ DH key agreement was originally described in the multiplicative group Zp of non-zero integers modulo a large prime p. Nowadays it is usual to define the group G in which the ∗ protocol takes place to be a subgroup of Zp of prime order q. This avoids several attacks and results in computational savings. Typical sizes in use today are 2048 bits for the length of p and 256 bits for the length of q. Several other algebraic groups have been proposed as the setting for DH key exchange. Elliptic curve groups in particular are popular today. They ∗ provide significant advantages over using Zp, because of their greater efficiency and compact representation. There are a variety of standardised elliptic curve groups available to protocol designers, like which is used in Tox. [BMS20]

Curve25519 and X25519

Curve25519 is a state-of-the-art ECDH function suitable for a wide variety of cryptographic applications. It was introduced by Daniel J. Bernstein in 2006. Each Curve25519 party has a 32-byte secret key and a 32-byte public key. Each pair of two Curve25519 parties has a 32-byte shared secret used to authenticate and encrypt messages between the two parties. Figure 2.4 shows the data flow from secret keys through public keys to a shared secret (cf. description of figure 2.3). [Ber06]

Figure 2.4.: Curve25519 data flow from secret keys through public keys to a shared secret (cf. [Ber06])

A hash of the shared secret Curve25519(a, Curve25519(b,9)) is used as the key for a secret- key authenticated-encryption system to simultaneously encrypt and authenticate messages [Ber06]. In case of Tox the secret-key authenticated-encryption system is XSalsa20-Poly1305, but instead of a hash the plain shared secret is used (i.e. Curve25519(a, Curve25519(b,9))).

On a low-level, the Curve25519 function is Fp-restricted x-coordinate scalar multiplication 255 on E(Fp2 ), where p is the 2 − 19 and E is the elliptic curve y2 = x3 + 486662x2 + x (see [Ber06] for more details). The original paper [Ber06] defined "Curve25519" as an X-coordinate DH system using that curve. Nowadays it has become increasingly common for "Curve25519" to refer to an elliptic curve. "Ed25519" clearly refers to an Edwards-coordinate signature system using that curve. Therefore Daniel J. Bernstein suggests the following terminology [Ber14]: • "X25519" is the recommended Montgomery-X-coordinate DH function. • "Ed25519" is the recommended Edwards-coordinate signature system. • "Curve25519" is the underlying elliptic curve.

11 Chapter 2. Background

2.2.3. Secure Channel Protocols

Key exchange protocols enable two parties that communicate over an adversary-controlled network to generate a common secret key. These protocols are essential for enabling the use of shared-key cryptography to protect data transmitted over insecure networks. Hence they are a central part for building secure communications (also known as secure channels) and are among the most commonly used cryptographic protocols. Contemporary examples include TLS, Secure Shell (SSH) and Internet Protocol Security (IPSec). [CK01] Canetti and Krawczyk define secure channel protocols as "network channel protocols that are simultaneously secure network authentication and secure network encryption protocols". To protect end-to-end communications, two parties exchange a secret session key and then use this key to encrypt and authenticated the transmitted data under symmetric cryptographic functions. In order for an AKE protocol to be considered secure it needs to guarantee that its strategy for securing data works correctly. Meaning, that by using a shared key provided by the AKE protocol one achieves sound secrecy and authentication. As it is common, this thesis will refer to a link between a pair of parties that achieves these properties as a secure channel. [CK01] Secure channel protocols (SCPs) all have a similar structure as shown in figure 2.5. They usually consist of a handshake phase which is in place to authenticate the involved parties and to establish shared session keys. In the transport phase (that follows after the handshake) the established shared secret key is used to encrypt (application) data. The handshake phase further is divided into a negotiation phase and an AKE phase (see figure 2.6). Most secure channel protocols have some sort of negotiation that happens before the real communication can start, such as defining the type of the AKE and which cipher should be used in this protocol session. The AKE phase then establishes the shared secret which is subsequently used in the transport phase for bulk data encryption. Depending on the SCP the negotiation and AKE phases can be independent or overlaid. [Per17]

Secure Channel Protocol Handshake Phase Authenticates and establishes shared secret keys

Transport Phase Uses shared secret keys to encrypt data

Figure 2.5.: Phases of a secure channel protocol (cf. [Per17])

12 Chapter 2. Background

Secure Channel Protocol Handshake Phase Negotiation

Authenticated Key Exchange (AKE)

Transport Phase

Figure 2.6.: Negotiation and AKE happen during the handshake phase of a secure channel protocol (cf. [Per17])

2.3. Tox

The development of Tox began in the wake of Edward Snowden’s leaks regarding the NSA’s spying activities and is intended as a Skype replacement. In 2013 a small group of developers began to work on a library implementing the Tox protocol (called c-toxcore7). The idea was to create a new IM application that works without requiring the use of any servers and without a possibility to disable the encryption features. The application should also be easy to use by a layperson. The resulting chat system is peer-to-peer and end-to-end encrypted. The toxcore library provides all of the messaging and encryption facilities and is completely decoupled from any user interface. An end-user needs a Tox client application which uses the c-toxcore library, like qTox8. Tox has thousands of users (including both the core library and the clients) and many voluntary contributors. [Imp19, Rob17] The features of Tox include IM, voice calls and video calls, screen and file sharing, and group chats [nur19]. Tox is also in use for other purposes besides IM9. It is a FLOSS project due to the use of the GPLv3 and comes without advertising. Development of toxcore is still ongoing and the whole development process occurs publicly [nur18a]. Terminology in context of Tox is as follows: • Tox is the name of the protocol in general • The implementation of Tox is Tox core, usually written as toxcore – a network library implementing the Tox protocol • The clients (using toxcore) have specific names, like qTox Tox uses Networking and Cryptography library (NaCl) respectively libsodium nowadays for its encryption and authentication. All Tox communications are encrypted (text, audio, video, file transfers etc.). Every person running a Tox client is also a Tox and contributes to the distributed network. A distributed hash table (DHT) is used to store peer information. The static long-term 32-byte X25519 public keys of users, followed by four bytes "NoSpam" (used for spam prevention) and a two bytes XOR checksum, are their Tox IDs (see figure 2.7 for an example in hexadecimal format). They are mapped to an IP address in the DHT. The IP addresses are encrypted and are then decrypted when a friend request is made with a

7https://github.com/TokTok/c-toxcore 8https://qtox.github.io/en.html 9https://toktok.ltd/integrations.html

13 Chapter 2. Background proper Tox ID. IP addresses are used to create a direct connection between friends. Tox IDs need to be exchanged out-of- (e.g. via ) because there is no central key repository. Initial trust establishment is therefore currently not in scope of the Tox protocol. Bootstrap nodes are used for the initial connection to the Tox network and are clients for DHT work only. A client connects to a bootstrap node if no other nodes in the network are known. Thus it’s required that bootstrap nodes are highly available (online most of the time), to have a static IP address or use domain names, to not change port numbers and to have static public keys10. A list of bootstrap nodes is hard-coded in a Tox client, but users can adapt these lists since all clients are open source software. Additionally users can run bootstrap nodes on their own and can also create a private Tox network. [Tok20, nur18b]

Figure 2.7.: An example Tox ID (cf. [Tok20])

Goals of the Tox protocol are [Tok20]: • Authentication: During a communication session both parties can be sure of the other party’s identity. • End-to-end encryption: The Tox protocol establishes E2EE communication links by deriving shared session keys using ECDH based on X25519. • Forward secrecy: Shared keys are renegotiated for each session. • Privacy: Tox aims to avoid identity leakage of parties involved in a communication link (i.e. their static long-term X25519 public keys11). This means that public keys are not transferred in cleartext during a Tox connection. • Resilience: Tox avoids relying on servers as much as possible. Communications are not transmitted via or stored on central servers. Anyone can run Tox bootstrap nodes and users don’t need to put any trust in them. • Minimum configuration: Tox aims to need nearly zero configuration and aims to make security easy to achieve for average users. • Non-goal : Anonymity is not in scope of the Tox protocol, but it is easy to integrate with software providing anonymity, such as Tor12. The Tox protocol consists of multiple modules, namely Crypto, DHT, TCP_Connection, Messenger, Friend_connection, Network, Onion and Net_crypto. The following enumeration provides a short description of all modules [Tok20]: • Network: This is the lowest module everything else depends on. • Crypto: This module contains all the functions and data types related to cryptog- raphy, including random number generation, encryption, decryption, key generation, operations on nonces and generation of random nonces. • DHT: This module is for opening direct UDP routes between peers (called hole punch- ing).

10Tox Bootstrap Nodes Status: https://nodes.tox.chat/ 11A long-term public key (or the Tox ID) of a Tox user is not enough information to establish a connection. To be able to do so, two users need to be friends, to be able to retrieve each others DHT public key (which is an independent X25519 public key) from the DHT. 12https://www.torproject.org/

14 Chapter 2. Background

• Onion: This module is to prevent peers that are not friends from finding out the tem- porary DHT public key from a known long-term public key of the peer and to prevent peers from discovering the long-term public key of peers when only the temporary DHT key is known. • TCP_connection: This module is for establishing of relayed TCP connections be- tween peers. • Net_crypto: This module represents the Tox UDP transport protocol (but is also used if friends are connected via TCP relays) to establish friend connections, to send data securely to friends, and provides ordered delivery and forward secrecy. The handshake including the AKE is also implemented in this module, therefore it’s the most important one in regard to this thesis. • Friend_connection: This module is on top of the DHT, Onion and Net_crypto modules, and links the three together. It takes care of establishing the connection to friends and provides the upper Messenger layer an interface to receive and send messages, add and remove friends and retrieve the connection status of friends (online or offline). • Messenger: This module is on top of all the others. List 2.1 shows the notation used for (cryptographic) values and operations in chapter 2:

List 2.1.: Notation used for (cryptographic) values and operations in chapter 2

priv pub • SA ,SA : X25519 static private and public keys of a peer A (32 byte each) priv pub • DHTA ,DHTA : X25519 DHT private and public keys of a peer A (32 byte each). The DHT key pair is renewed every time the Tox instance is closed or restarted.

priv pub • EA ,EA : X25519 ephemeral session private and public key of a peer A (32 byte each)

• NA, BaseNonceA: 24-byte random nonce value generated by peer A • ECDH(private key, public key): X25519 ECDH computation of a 32-byte shared secret key given a 32-byte public key and 32-byte a secret key (cf. [LHT16])

• KAB: Ephemeral shared key calculated from one private and one public X25519 key priv pub (e.g. KAB = ECDH(SA , SB ))

• CookieA, OtherCookieA: 112-byte cookie created by peer A

• kA: 32-byte secret key (random bytes), used by peer A to encrypt their cookies (see figure 2.9), which are transmitted in cookie response and handshake packets

• ENC(key, nonce, plaintext, ad): XSalsa20-Poly1305 authenticated encryption with associated data (AEAD) of an arbitrary length plaintext with a 32-byte key and a 24- byte nonce, returns a ciphertext and a 16-byte authentication tag; Arbitrary length associated data ad is authenticated together with ciphertext (cf. [Rog02]), but may be empty

• DEC(key, nonce, ciphertext, ad): XSalsa20-Poly1305 AEAD decryption of an arbitrary length ciphertext with a 32-byte key and a 24-byte nonce, verifies the 16-byte authentication tag, returns a plaintext; Arbitrary length associated data ad must be the same as during encryption, but may be empty

15 Chapter 2. Background

• MACA: Message Authentication Code (MAC) – 16-byte authentication tag calculated by ENC() and DEC()

• echoIDA: 8-bytes of random numbers, used by peer A to verify validity of cookie response packets

• HASH(input): SHA512(input) returns the 64-byte SHA512 hash of input

priv pub • GENERATE_KEYPAIR(): Returns a new X25519 key pair (e.g. {EA , EA }) • ε: Empty string

• L2B(number): takes a 24-byte number/nonce and returns the last two bytes of the number (Big Endian)

2.3.1. Cryptographic Primitives used in Tox

The Tox protocol implementation’s cryptographic primitives are based on NaCl respectively libsodium nowadays to achieve encryption and authentication. According to the projects website, NaCl "is a new easy-to-use high-speed software library for network communication, encryption, decryption, signatures etc. NaCl’s goal is to provide all of the core operations needed to build higher-level cryptographic tools" [Ber16]. Other libraries also exist for these operations, but NaCl advances the state of the art by improving security, usability and speed [Ber16]. The main goal while creating NaCl, was to "avoid various types of cryptographic disasters suffered by previous cryptographic libraries such as OpenSSL13". NaCl provides extremely high speed operations and is not vulnerable to attacks such as padding oracles. [BLS12] The current implementation of c-toxcore uses libsodium, which "is a portable, cross- compilable, installable, packageable fork of NaCl, with a compatible API, and an extended API to improve usability even further" [Den19]. X25519 [Ber06] key pairs are used for various purposes in Tox (e.g. AKE). They are generated using the crypto_box_keypair() function of the libsodium library. A public key can be computed from a X25519 secret key by using the libsodium function crypto_s calarmult_base(). [Tok20] Combined keys (shared keys) are computed from a X25519 secret key and a X25519 public key using the function crypto_box_beforenm(). This function is used to perform authen- priv pub priv pub ticated key agreement between two peers. Given two key pairs {SA ,SA } and {SB ,SB } priv pub priv pub the combined key computed from {SA ,SB } equals the one computed from {SB ,SA }. This makes symmetric encryption possible because peers can derive the same shared key from their own private key and their peer’s public key. The shared key computation is the most resource-intensive part of the encryption/decryption process. Therefore this key is only calculated once per session (between two peers) in Tox to reduce resource usage. [Tok20] Random nonces in Tox are generated using the cryptographically secure random number generator from the libsodium library (randombytes()). [Tok20] The encryption function crypto_box_afternm() from libsodium takes a shared key, a nonce and a plaintext as parameters and returns a ciphertext. For decryption the function crypto_box_open_afternm() is used, which needs to be provided with the same shared

13https://www.openssl.org/

16 Chapter 2. Background key, the same nonce and the ciphertext as input, to return the plaintext (or an error). The crypto_box functions from libsodium use the XSalsa20 stream cipher [Ber11] for encryption with Poly1305 [Ber05] for authentication. [Tok20]

2.3.2. Tox Protocol Packets

All Tox packet types are wrapped in protocol packets. These consist of a packet kind14 and payload. Packet kinds are represented as a single byte. The payload is an arbitrary sequence of bytes. Inside protocol packet payloads other packet types can specify additional packet kinds. For example, inside a crypto data packet (identified by byte 0x1b) the Messenger module defines its protocols for messaging, file transfers etc. Protocol packets themselves are not encrypted, but their payload may be. [Tok20] In table 2.1 all handshake-relevant packet kinds and their byte representation are shown. The corresponding protocol packets and their purpose are described in detail in section 2.4. All packet kinds and their byte representation are shown in table A.1 in the appendix.

Byte value Packet kind Length Packet format 0x18 Cookie Request 145 bytes see figure 2.8 (no packet) Cookie 112 bytes see figure 2.9 0x19 Cookie Response 161 bytes see figure 2.10 0x1a Crypto Handshake 385 bytes see figure 2.11 0x1b Crypto Data 19 bytes + variable payload see figure 2.12

Table 2.1.: Handshake-relevant packet kinds and their byte representation (cf. [Tok20])

0x18 (1 byte packet kind) pub DHTA (32 bytes) cookie_request NA (24 bytes)  pub  ENC() encrypted part SA (32 bytes)   cookie Padding (32 bytes) key = KAB =  priv pub echoIDA (8 bytes)  ECDH(DHTA ,DHTB ) cookie_request MACA (16 bytes)

Figure 2.8.: Cookie request packet from peer A (145 bytes)

cookie NB (24 bytes)  Timestamp (8 bytes)   ENC() encrypted part Spub (32 bytes) A key = k pub  B DHTA (32 bytes) 

cookie MACB (16 bytes)

Figure 2.9.: Cookie from peer B (112 bytes)

14The term "packet kind" is unusual, but this is the term used in the Tox specification (see [Tok20]).

17 Chapter 2. Background

0x19 (1 byte packet kind) cookie_response NB (24 bytes) ) ENC() encrypted part CookieB (112 bytes) cookie key = KAB = echoIDA (8 bytes) priv pub ECDH(DHTB ,DHTA ) cookie_response MACB (16 bytes)

Figure 2.10.: Cookie response packet from peer B (161 bytes)

0x1a (1 byte packet kind)

CookieB (112 bytes) handshake NA (24 bytes)  BaseNonce (24 bytes)  A  ENC() encrypted part Epub (32 bytes)  A key = Khandshake = HASH(Cookie ) (64 bytes) AB B  priv pub  ECDH(SA ,SB ) OtherCookieA (112 bytes) 

handshake MACA (16 bytes)

Figure 2.11.: Handshake packet from peer A (385 bytes)

0x1b (1 byte packet kind) encrypted_packet L2B(BaseNonceA + P acket#) (2 bytes) ENC() encrypted part o data Payload (variable length bytes) key = KAB = priv pub encrypted_packet ECDH(EA ,EB ) MACA (16 bytes)

Figure 2.12.: Encrypted data packet from peer A (19 bytes + variable length payload)

2.4. Current Cryptographic Handshake and AKE in Tox

Tox’ cryptographic handshake is implemented in the Net_crypto module. Net_crypto rep- resents the Tox transport protocol, which is used to establish connections to friends and to send encrypted data to them. Besides encryption it provides ordered delivery and perfect forward secrecy, but no KCI-resistance. It is based on UDP, but for simplicity it is also used if two peers connect over TCP relays. Therefore a Tox connection can switch between UDP and TCP. For example, two Tox peers (friends) might initially connect over TCP, but switch to UDP a few seconds later because a direct UDP connection is now possible. A UDP route is created by the DHT module and a relayed TCP connection is created by the TCP_connection module. UDP is preferred over TCP because it’s direct and not limited by possibly congested TCP relays. Since the Tox protocol is based on UDP, it must account for possible packet loss and packets arriving in the wrong order. In general a peer can only connect to another peer using the Tox transport protocol if the real static public key and DHT public key of this peer is known. [Tok20] The peer that wants to start a new handshake is referred to as initiator (or (A)lice), while the peer that they try to communicate with is called the responder (or (B)ob). In

18 Chapter 2. Background practice both peers can be initiator and responder at the same time. For simplicity this description assumes that only one peer is an initiator and the other peer is only responding (cf. ideal handshake in figure 2.13 and realistic handshake in figure 2.14). In the following, Tox’ handshake is described in detail. This section concludes with enumeration 2.2, which shows the detailed message flow and computations during an "ideal handshake" scenario.

Ideal handshake scenario Alice (initiator) Bob (responder) Cookie request

Cookie response

Handshake packet

Accepts connection Handshake packet

Accepts connection Encrypted packet

Confirms connection Encrypted packet

Confirms connection

...... Connection successful ......

Encrypted packets

Encrypted packets

Figure 2.13.: Tox ideal handshake scenario (cf. [Tok20])

Before sending an actual handshake packet, the initiator must obtain a cookie from the responder. The cookie created by B, which is intended to be used by A, contains the current timestamp, the static public key of A and the DHT public key of A (see figure 2.9). The corresponding bytes are encrypted with a secret symmetric key kB which is only known to the peer who created the cookie (i.e. B). The same key is used to encrypt all cookies of this peer. [Tok20] A cookie is obtained by sending a cookie request packet (see figure 2.8). The encrypted part in the cookie request packet is encrypted with ENC() by deriving a temporary shared key priv pub cookie_request by computing ECDH(DHTA , DHTB ) and by using the included nonce NA . Toxcore currently sends one cookie request packet per second for eight seconds before it kills the connection if there are no responses. This cookie phase is in place to confirm to the responder that the initiator is able to receive responses in order to prevent certain types of denial of service (DoS) attacks (e.g. IP address spoofing). [Tok20]

19 Chapter 2. Background

Realistic handshake scenario Alice (initiator) Bob (responder) Cookie request

Packet lost Cookie request

Cookie response

Bob randomly starts new connection to Alice Cookie request

Cookie response

Handshake packet

Accepts connection Handshake packet

Accepts connection Encrypted packet

Confirms connection Encrypted packet

Confirms connection

...... Connection successful ......

Encrypted packets

Encrypted packets

Figure 2.14.: Tox realistic handshake scenario (cf. [Tok20])

The responder will answer by sending a cookie response packet (see figure 2.10) to the initiator including the echoIDA, that was sent by the initiator in the cookie request packet. The encrypted part of the cookie response packet is encrypted with the same shared key as the cookie request packet. The echoID is for the initiator to confirm, that the cookie response received, is a valid response to their request. This packet contains the cookie of B (i.e. CookieB), which the initiator must then include in the crypto handshake packet to initiate the actual authenticated key exchange. The responder must not use the information from the cookie request packet for anything, they must only create a cookie and send the response. If a peer would allocate long-term memory for each cookie request packet received

20 Chapter 2. Background this could lead to DoS. The cookie response packet must be sent using the exact same link as the cookie request was sent from. For example, if a cookie request is sent using UDP with IP address X and port Y , it must be sent back using UDP to IP X and port Y . The timestamp included in the cookie is used to prevent cookie packets that are too old from being used. The timeout for cookie packets in toxcore is 15 seconds. If a cookie packet is used more than 15 seconds after it was created it will be seen as invalid. [Tok20]

Now the AKE phase of the handshake starts. The cookie in the handshakeA packet (see figure 2.11) is the cookie obtained from the responder B in the cookie phase. The cookie may also be obtained via a handshake packet from the responder, if this peer also started a hand- shake with their own cookie phase (cf. figure 2.14). This cookie is then called OtherCookie. Besides the different naming, cookies obtained via cookie response packets and handshake packets are the same. The nonce included in the handshake packet is used to encrypt the handshake encrypted part of the handshake packet together with a shared secret KAB (which is priv pub priv pub based on the static long-term keys of both peers, i.e. {SA ,SB } respectively {SB ,SA }) using ENC(). The encrypted part contains a BaseNonceA and an ephemeral X25519 session pub priv public key EA . The private counterpart of this session key pair EA needs to be saved, to pub be able to compute the ephemeral shared session key later (after EB was received). The BaseNonceA is used by A to encrypt the data packets sent to B, adding +1 for each data packet sent. Therefore both peers need to save both BaseNonces (to encrypt packets and to decrypt incoming encrypted data packets). The hash of the cookie in the encrypted part is to prevent that an attacker saves a previously valid handshake packet, then replaces the cookie inside with a newer one and sends this crafted handshake packet. This would be as bad as if they could replay a handshake packet. The OtherCookieA is a valid cookie that the initia- tor puts into the handshake packet to enable the responder to reply with a valid handshake packet without having to send a cookie request to obtain a cookie from the initiator. [Tok20] A handshake packet is sent by both sides of the connection. The peer receiving a handshake packet will check if the cookie is valid by decrypting it using their secret symmetric key (i.e. kA in case of A and kB in case of B), if the decryption of the encrypted part of the handshake packet works and validates, if the cookie hash is valid, and if the long-term public key belongs to a known friend. If all these conditions are met, the connection is set to the accepted state, but is not confirmed yet. If there is no existing connection to this peer identified (via the pub pub long-term public key SA respectively SB ) to set to accepted, one will be created with this state. If a connection already exists, but with a not yet accepted state, this connection is set to accepted. If a connection with the confirmed state exists for this peer, the handshake packet will be ignored and discarded because otherwise late handshake packets could kill the connection. [Tok20] Handshake packets must be created only once during a connection between two peers, but must be sent in intervals until both are sure the other received them. This is the case when a valid encrypted data packet is received and decrypted. After both peers set the connection state to confirmed, the transport phase starts. Due to how the Tox protocol is designed, only one connection is possible at a time between two peers. Overall the handshake was designed like this to also successfully establish a connection between the two peers, if both try to initiate a connection at the same time (cf. figure 2.14). [Tok20] The payload of the data packet (see figure 2.12) is encrypted with the shared ephemeral data session key KAB and the BaseNonce of the peer plus the packet number (starting by 0). To be able to decrypt packets received by a peer, the BaseNonce of this peer is saved after receiving the handshake packet. [Tok20]

21 Chapter 2. Background

These are all possible states of a Tox crypto connection between two peers (cf. [Tok20]): 1. Cookie requested (= CRYPTO_CONN_COOKIE_REQUESTING): Set when sending the first cookie request packet. Peer keeps sending cookie request packets (cookie "negoti- ation" phase of Tox’ handshake). 2. Not accepted (=CRYPTO_CONN_HANDSHAKE_SENT): Set after a cookie response packet was received from the other peer. Therefore a peer in this state starts to send handshake packets (AKE phase of Tox’ handshake). 3. Accepted (= CRYPTO_CONN_NOT_CONFIRMED): Set after a handshake packet has been received from the other peer, but no encrypted packets yet. Therefore a peer in this state continues (or starts) sending handshake packets because this peer cannot know if the other peer has received them already (AKE phase of Tox’ handshake). 4. Confirmed (= CRYPTO_CONN_ESTABLISHED): Set after a valid encrypted packet has been received from the other peer. The Connection is fully established. Therefore a peer in this state stops sending handshake packets (Tox’ handshake is finished, transport phase of the Tox protocol starts). The following list 2.2 shows the detailed message flow and computations during an "ideal handshake" scenario (see figure 2.13 for a high level overview):

List 2.2.: Message flow and computations during an "ideal" Tox handshake

• A: ephemeral X25519 session key pair generation

priv pub {EA ,EA } = GENERATE_KEYPAIR() (2.1)

• A: shared ephemeral symmetric session key derivation (cookie phase)

cookie priv pub KAB = ECDH(DHTA ,DHTB ) (2.2)

• A: sets connection status to CRYPTO_CONN_COOKIE_REQUESTING

• A → B: creates and sends cookie request packet CookieRequestA

pub cookie_request {0x18,DHTA ,NA , cookie cookie_request pub ENC(KAB ,NA , {SA , Padding, echoIDA}, ε), (2.3) cookie_request MACA }

• B: shared ephemeral symmetric session key derivation (cookie phase)

cookie cookie priv pub KBA = KAB = ECDH(DHTB ,DHTA ) (2.4)

cookie_request • B: retrieves plaintext from CookieRequestA and verifies MACA

pub {S , Padding, echoIDA} = A (2.5) cookie cookie_request DEC(KBA ,NA , ciphertext, ε)

• B: creates CookieB

cookie CookieB = {NB , (2.6) cookie pub pub cookie ENC(kB,NB , {Timestamp,SA ,DHTA }, ε), MACB }

22 Chapter 2. Background

• B → A: creates and sends cookie response packet CookieResponseB

cookie_response {0x19,NB , cookie cookie_response ENC(KBA ,NB , {CookieB, echoIDA}, ε), (2.7) cookie_response MACB }

cookie_response • A: retrieves CookieB, verifies echoIDA and MACB

{CookieB, echoIDA} = (2.8) cookie cookie_response DEC(KAB ,NB , ciphertext, ε)

• A: creates CookieA = OtherCookieA

cookie CookieA = OtherCookieA = {NA , (2.9) cookie pub pub cookie ENC(kA,NA , {Timestamp,SB ,DHTB }, ε), MACA }

• A: shared symmetric session key derivation (AKE phase)

handshake handshake priv pub priv pub KAB = KBA = ECDH(SA ,SB ) = ECDH(SB ,SA ) (2.10)

• A → B : creates and sends handshake packet HandshakeA

handshake {0x1a, CookieB,NA , handshake handshake pub ENC(KAB ,NA , {BaseNonceA,EA , (2.11) handshake HASH(CookieB), OtherCookieA}, ε), MACA }

• A: sets connection status to CRYPTO_CONN_HANDSHAKE_SENT

pub • B: retrieves BaseNonceA, EA , HASH(CookieB), OtherCookieA and verifies handshake HASH(CookieB) and MACA

pub {BaseNonceA,E , HASH(CookieB), OtherCookieA} = A (2.12) handshake handshake DEC(KBA ,NA , ciphertext, ε)

• B: ephemeral X25519 session key pair generation

priv pub {EB ,EB } = GENERATE_KEYPAIR() (2.13)

• B: shared ephemeral symmetric session key derivation (data transport phase)

data data priv pub priv pub KBA = KAB = ECDH(EB ,EA ) = ECDH(EA ,EB ) (2.14)

• B: shared symmetric session key derivation (AKE phase15)

handshake handshake priv pub priv pub KBA = KAB = ECDH(SB ,SA ) = ECDH(SA ,SB ) (2.15)

• B: sets connection status to CRYPTO_CONN_NOT_CONFIRMED

15 data handshake In toxcore KBA is indeed calculated before KBA for the responder

23 Chapter 2. Background

• B → A : creates and sends handshake packet HandshakeB

handshake {0x1a, CookieA,NB , handshake handshake pub ENC(KBA ,NB , {BaseNonceB,EB , (2.16) handshake HASH(CookieA), OtherCookieB}, ε), MACB }

pub • A: retrieves BaseNonceB, EB , HASH(CookieA), OtherCookieB and verifies handshake HASH(CookieA) and MACB

pub {BaseNonceB,E , HASH(CookieA), OtherCookieB} = B (2.17) handshake handshake DEC(KAB ,NB , ciphertext, ε)

• A: shared ephemeral symmetric session key derivation (data transport phase)

data data priv pub priv pub KAB = KBA = ECDH(EA ,EB ) = ECDH(EB ,EA ) (2.18)

• A: sets connection status to CRYPTO_CONN_NOT_CONFIRMED

• B → A: sends encrypted packet EncryptedB

{0x1b, L2B(BaseNonceB + P acket#), data data (2.19) ENC(KBA , BaseNonceB + P acket#, payload, ε), MACB }

data • A: retrieves payload from encrypted packet EncryptedB and verifies MACB

data payload = DEC(KAB , BaseNonceB + P acket#, ciphertext, ε) (2.20)

• A: sets connection status to CRYPTO_CONN_ESTABLISHED

• A → B: sends encrypted packet EncryptedA

{0x1b, L2B(BaseNonceA + P acket#), data data (2.21) ENC(KAB , BaseNonceA + P acket#, payload, ε), MACA }

data • B: retrieves payload from encrypted packet EncryptedA and verifies MACA

data payload = DEC(KBA , BaseNonceA + P acket#, ciphertext, ε) (2.22)

• B: sets connection status to CRYPTO_CONN_ESTABLISHED

2.4.1. Security Properties of the Tox AKE

This section shortly lists the security properties provided by Tox AKE phase during the Tox handshake (see section 2.2.1 for definitions): • Forward and Backward Secrecy: Tox uses fresh ephemeral X25519 key pairs to derive a symmetric session key. • Mutual Authentication: Tox uses the static key pairs of both parties to encrypt handshake messages. This authenticates both parties.

24 Chapter 2. Background

• Deniability (also called participant repudiation or identity hiding): Tox users can deny having taken part in a communication session. Communications are authen- ticated, but not signed, and are therefore deniable. Messages are authenticated with shared session keys by using an AEAD cipher rather than being signed with long-term keys. Participant repudiation also provides message repudiation and message unlinka- bility. • Key Confirmation • No KCI-resistance: Tox AKE is vulnerable to KCI-attacks.

2.5. Noise Protocol Framework

The Noise Protocol Framework (hereafter referred to as "Noise") is a framework created by Trevor Perrin [Per18] that helps to create secure channel protocols (like TLS and SSH) based on Diffie-Hellman key agreement. This framework can be used to describe single message protocols as well as interactive protocols. It was developed to prevent the problems and vulnerabilities of cryptographic protocols like the Tox handshake which is "home-brewed". [Per18] Therefore the framework is intended to be used by cryptographic protocol designers. Noise is the basis for multiple libraries which provide a simple way to implement such protocols. As of April 2020, the framework is still outlined as unstable. The current revision #34 is from 07.11.2018 [Per18]. Nevertheless, Noise protocols are already in use in some applications: • WireGuard uses it for establishing Virtual Private Network (VPN) connections (cf. [Don17b]) • WhatsApp uses it for encrypted client-to-server communication (cf. [Wha17]) • uses it for internal server-to-server communication (cf. [Hub19]) • I2P uses it for NTCP2, I2Ps AKE protocol (cf. [vil18]) • The Bitcoin Lightning Network uses it for encrypted and authenticated transport be- tween nodes (cf. [The20])

2.5.1. Noise Protocols

A Noise protocol based on this framework starts with two parties exchanging handshake messages. During this handshake phase the parties exchange DH public keys and perform a sequence of DH operations which are defined by the used Noise pattern. The DH results get hashed into a shared secret key. After the successfully finished handshake phase each party can use this shared key to send encrypted transport messages. [Per18] The Noise framework supports handshakes where each party has a long-term static DH key pair and/or an ephemeral DH key pair. A Noise handshake is described by a simple frame- work language which consists of tokens. These tokens are arranged into message patterns. Handshake patterns are built using these message patterns. The tokens specify which DH public keys comprise a handshake message, and which DH operations are performed when sending or receiving that message. A handshake pattern specifies the order in which these messages are exchanged to create a cryptographic handshake. These handshake patterns can be instantiated by DH functions, cipher functions and hash functions to give a concrete Noise protocol (see section 2.5.2 for more details). [Per18]

25 Chapter 2. Background

In Noise each party maintains a set of variables during the handshake [Per18]: • s, e: The local parties static and ephemeral key pairs. These may be empty. • rs, re: The remote party’s static and ephemeral public keys. These may be empty. • h: All the handshake data that has been sent and received gets hashed and saved to the handshake hash value. • ck: All DH outputs get hashed into the chaining key. After the successfully finished handshake the encryption keys for transport messages are derived from the chaining key. • k, n: The encryption key (which may be empty) and a counter-based nonce. Whenever a new chaining key is calculated (i.e. after every DH operation), a new k is also calculated and n is set to zero. This key and nonce are used to encrypt the static long- term public keys and the payloads that are sent during the handshake. Encryption with k is performed in an AEAD cipher mode (in the sense of Rogaway [Rog02]) which uses the current h as associated data to cover it by the AEAD authentication. Therefore this provides (some) confidentiality and key confirmation in the handshake phase. A Noise handshake message consists of DH public keys followed by payload data chosen by the application. To send a handshake message, the sender processes each token from the current message pattern. These Noise tokens are [Per18]: • e: The sender generates a fresh ephemeral key pair and stores it in the e variable, writes the ephemeral public key in cleartext into the message buffer and hashes the public key into the handshake hash state h. • s: The sender writes its static long-term public key in plaintext or encrypted (if a k is already available) into the message buffer and hashes the encrypted key into the handshake hash state h. • ee, se, es, ss: A DH is performed between the initiator’s static or ephemeral key pair (determined by the first letter) and the responder’s static/ephemeral key pair (determined by the second letter). The result is hashed with the current chaining key to derive a new ck and k. Additionally the nonce n is set to zero. As a last step (i.e. after processing the final token), the sender writes the payload into the message buffer, encrypts it if k is not empty, and hashes the result with the old h to calculate a new h. There are also rules for sending and receiving handshake messages which are dependent on the sequence of tokens from a message pattern. An example handshake pattern is shown in figure 2.15. Initially it was planned to implement the new Tox handshake using this Noise KK pattern, but this was not possible due to reasons explained in detail in section 4.1. Therefore the new Tox handshake was implemented based on the Noise IK pattern (see figure 2.16). In the Noise KK handshake pattern both parties have pre-knowledge of the other’s static long-term public key and therefore use it for 0-RTT encryption (this is also the case with the current Tox handshake). The initiator’s pre-message -> s is listed first. The "..." serve as delimiter for pre-messages and actively exchanged messages. The initiator sends the first message which consists only of an unencrypted fresh ephemeral public key. Additionally, the initiator performs a first DH operation on their ephemeral private key and the responders static public key and a second one with their static private key and the others static public key. Both results are hashed into the chaining key and k. The responder answers with their fresh ephemeral public key, also performs two DH operations and hashes the results into ck and k. Actually all four DH operations happen on both sides, but this will be

26 Chapter 2. Background described in detail in section 4.1.1. Both handshake message payloads may be empty, but the payload ciphertext will still contain authentication data (a 16-byte authentication tag), since symmetric encryption is performed in an AEAD mode.

KK: -> s <- s ... -> e, es, ss <- e, ee, se

Figure 2.15.: In the Noise KK handshake pattern both parties have pre-knowledge of the other’s static public key. (cf. [Per18])

In the Noise IK handshake pattern only the initiator has pre-knowledge of the responder’s static long-term public key, but 0-RTT encryption is still possible. There is only one pre- message <- s from the responder to the initiator. In this pattern the message of the initiator contains an unencrypted fresh ephemeral public key and their encrypted static public key. The encryption is possible because of a first DH operation on the initiator’s ephemeral private key and the responders static public key. A second DH operation is performed with the initiators static private key and the responders static public key. Both results are hashed into the chaining key and k. The responders message and operations are the same as in the Noise KK pattern, besides that he retrieves the initiators static key from the message sent by the initiator.

IK: <- s ... -> e, es, s, ss <- e, ee, se

Figure 2.16.: In the Noise IK handshake pattern the initiator has pre-knowledge of the re- sponder’s static public key. (cf. [Per18])

In general static public keys and payloads will be transmitted in cleartext if they are sent prior to a DH operation. Note that in the KK pattern example no static keys are transferred because they were exchanged beforehand. The security properties for the handshake pay- loads are (usually) weaker than the security properties of the transport payloads (see section 2.5.3 for details). Underlying these operations based on the sequence of tokens, there is a sophisticated state machine logic which defines the processing rules, such as mixing derived keys together. Readers are directed to the Noise specification for further details about the protocol framework and the processing rules. An extensive example for the processing of a Noise protocol handshake is given in section 4.1.

27 Chapter 2. Background

Noise defines three "objects" which encapsulate state variables and contain functions which implement the processing logic. These three objects have a hierarchical order. From the lowest layer to the highest, the objects are [Per18]: • CipherState: This object contains the k and n variables, which are used to en- crypt and decrypt ciphertexts. In the handshake phase each party maintains one CipherState, but in the transport phase each party uses one CipherState for sending and one for receiving. • SymmetricState: This object contains a CipherState, plus a ck and h variable. It encapsulates the symmetric cryptography used by Noise. The SymmetricState can be deleted after a successful handshake. • HandshakeState: This object contains a SymmetricState plus all DH variables (s, e, rs, re) and a variable containing the handshake pattern. The Handshake State can be deleted after a successful handshake.

2.5.2. Noise Protocol Names

A Noise handshake pattern is not enough to design a full Noise protocol. Application devel- opers respectively protocol designers are responsible to choose the cryptographic primitives to create a Noise protocol based on a Noise pattern (cf. figure 2.17). An Example for a Noise protocol name is: • Noise_IK_25519_ChaChaPoly_SHA512 Every name starts with Noise, followed by the name of the Noise pattern (e.g. IK), the DH function (e.g. X25519), the cipher function (e.g. ChaChaPoly which is short for ChaCha20- Poly1305) and a hash function (e.g. SHA512). The different sections of the protocol name are separated by an underscore (_). The resulting name must not exceed 255 bytes.

Noise Protocol Handshake Pattern (abstract AKE)

Instantiated by Instantiated by

Public key crypto Symmetric crypto

Figure 2.17.: Noise protocol components (cf. [Per17])

The following cryptographic primitives are supported according to the Noise specification [Per18]: • DH functions: Curve25519 (also known as X25519 [LHT16]) and (also known as X448 [LHT16]) • Cipher functions: ChaCha20-Poly1305 [LN15] (ChaChaPoly) and AES256 with GCM (AESGCM) – Cipher keys are 256 bits and nonces are 64 bits. • Hash functions: SHA256, SHA512, BLAKE2s [SA15], BLAKE2b [SA15] Please see the Noise specification [Per18] section 15 for detailed design rationales.

28 Chapter 2. Background

2.5.3. Noise Payload Security Properties

Every payload in a Noise protocol is assigned a so-called "source" property regarding the degree of authentication of the sender provided to the recipient, and a so-called "destination" property regarding the degree of confidentiality provided to the sender. Therefore, depending on the Noise pattern’s authentication and confidentiality properties, a Noise protocol can provide authentication and integrity, key confirmation, KCI-resistance, forward secrecy and resistance against replay attacks. The Noise specification defines three payload authentication properties (therefore source properties) [Per18]: 0. No authentication16: Any party may have sent this payload, especially an active attacker. 1. Sender authentication vulnerable to KCI: The authentication of the sender is based on a static-static DH operation (i.e. "ss"). If the static long-term private key of the recipient is compromised, an attacker can forge this authentication. 2. Sender authentication resistant to KCI: The authentication of the sender is based on an ephemeral-static DH operation (i.e. "es" or "se") involving the static key pair of the sender and the ephemeral key pair of the recipient. If the corresponding private keys are secure, an attacker cannot forge this authentication. The Noise specification defines six payload confidentiality properties (therefore destination properties) [Per18]: 0. No confidentiality: The payload is not encrypted and sent in cleartext. 1. Encryption to an ephemeral recipient: The payload is encrypted based on an ephemeral-ephemeral DH operation (i.e. "ee") and therefore provides forward se- crecy. Any party may have sent this payload, especially an active attacker because the sender has not authenticated the recipient. 2. Encryption to a known recipient, forward secrecy for sender compromise only, vulnerable to replay: The payload’s encryption is only based on DH operations involving the static key pair of the recipient. This payload can be decrypted by an attacker if the recipient’s static private key is compromised. A replay of this message is also possible because there is no ephemeral key from the recipient involved. 3. Encryption to a known recipient, weak forward secrecy: The payload’s encryp- tion is based on an "ee" DH and also an "es" DH operation (involving the static key pair of the recipient). However, the sender has not verified that the ephemeral public key is from the recipient. Therefore an attacker may have forged the ephemeral pub- lic key and could decrypt the payload if they have compromised the recipients static private key. 4. Encryption to a known recipient, weak forward secrecy if the sender’s private key has been compromised: The payload’s encryption is based on an "ee" DH and also on an "es" DH operation (involving the recipients static key pair). However, the recipients ephemeral and static public key has only been verified based on DH operations involving the sender’s static private key. Therefore an attacker, who compromised the senders static private key can forge the recipients ephemeral public key. If the attacker would later compromise the (intended) recipients static private key, they could decrypt the payload.

16The source and destination properties enumerations start with 0 to be compliant with the Noise specification (cf. [Per18]).

29 Chapter 2. Background

5. Encryption to a known recipient, strong forward secrecy: The payload’s en- cryption is based on an "ee" and an "es" DH operation (with the recipients static key pair). If the ephemeral private keys are secure, and an attacker is not actively impersonating the recipient (with the recipients compromised static private key), this payload cannot be decrypted.

2.5.4. Formal Verification of Noise Handshake Pattern Security

The security properties of Noise patterns are formally verified. In 2018, Andris Suter-Dörig created "a tool which generates symbolic models for protocols given as Noise patterns and verifies a host of properties on these models using the Tamarin prover". They used this tool to verify all source and destination properties on a selection of 59 handshake patterns. [SD18] In 2019, Kobeissi et. al. presented "Noise Explorer, an online engine for designing, reason- ing about, formally verifying and implementing arbitrary Noise Handshake Patterns". This Noise Explorer is based on the ProVerif symbolic protocol verifier and "can validate any Noise Handshake Pattern and then translate it into a model ready for automated verification and also into a production-ready software implementation written in Go or in Rust". They used Noise Explorer to analyze more than 57 handshake patterns. Kobeissi et al. confirmed the stated security goals for 12 fundamental patterns, including the KK and IK pattern, and provide precise properties for the rest. Their work is consolidated into a usable online tool17. [KNB19] Independently and concurrent to the work of Kobeissi et al., Dowling et al. analyzed Noise patterns based on the authenticated and confidential channel establishment (ACCE) model. They provide full security proofs for eight of the 15 basic Noise patterns. [DRS19] Guillaume Girol also designed a tool using the "Tamarin prover" as a backend to determine the security properties of any given two-way Noise pattern. The difference with the work of Kobeissi et al. and Suter-Dörig mainly lies in the properties that were considered. The tool was applied to a set of 53 patterns to confirm and refine existing security analysis on these patterns. [Gir19]

17Design and Explore Noise Handshake Patterns: https://noiseexplorer.com/

30 3. Key Compromise Impersonation and Tox

In chapter 2 the background of this thesis, including a detailed description of the Tox hand- shake, was presented. This chapter starts with a general explanation and definition of KCI respectively KCI-resistance. Afterwards a short overview of the KCI-vulnerability in Tox’ AKE is given. Furthermore this chapter outlines the prerequisites that are necessary to con- duct a KCI-attack on Tox. Based on these prerequisites, three feasible attack scenarios are presented. For one of these attack scenarios it is described how a potential attack program could be implemented. Note that this chapter uses the same notation for (cryptographic) values and operations as chapter 2 (see enumeration 2.1).

3.1. Key Compromise Impersonation

Suppose an adversary Mallory has learned the private key of Alice for example by compro- mising the machine running an instance of the protocol in question (e.g. with the private key stored in memory). Mallory may now be able to mount the following attacks against the protocol [Str06]: 1. Impersonate Alice in a protocol run 2. Impersonate a different party (e.g. Bob) in a protocol run with Alice (KCI-attack) In attack #1 Mallory can send messages on behalf of Alice and these will be accepted as authentic by e.g. Bob. In attack #2 Mallory could successfully establish a session with Alice while masquerading as another party (e.g. Bob), which is known as Key Compromise Impersonation. [Str06] Strangio points out "that long-term key compromise can lead to undesirable consequences at least until the corrupted principal discovers that their key was compromised". Addition- ally, protocol designers are often concerned with forward secrecy and seem to ignore key compromise impersonation. As a result, many protocols are designed without considering KCI-resilience as a security goal. Strangio argues that "key compromise impersonation is not less important than forward secrecy and one should require that a secure key agreement protocol be also KCI-resilient since this security attribute is also related to party corruption". [Str06] KCI as an attribute of key agreement protocols was first identified by Blake-Wilson et al. They define it as follows [BWJM97]: Suppose i’s secret value is disclosed. Clearly an adversary that knows this value can now impersonate i, since it’s precisely this value that identifies i. However, it may be desirable that this loss does not enable an adversary to impersonate other entities to i.

31 Chapter 3. Key Compromise Impersonation and Tox

Strangio’s formal definition of KCI-resilience respectively KCI-resistance is as follows [Str06]: A key agreement protocol is KCI-resilient if compromise of the long-term key of a specific principal does not allow the adversary to establish a session key with that principal by masquerading as a different principal. In a real world scenario, a KCI-attack is performed as a Man-in-the-Middle attack. To pre- vent KCI-attacks either the session key should be computed in such a way that an adversary is unable to cause the corrupted party (e.g. A) to accept a particular session key without priv the adversary knowing the private key of the party they are impersonating (e.g. B, SB ) priv and/or the session-specific data of A (EA ). An alternative would be the approach used by the MQV protocol where such attacks are avoided by destroying the algebraic structure of the group. [Str06] Krawczyk’s HMQV protocol is an example of a key agreement protocol that has been proved secure against KCI-attacks [Kra05]. HMQV is a provable secure variant of the Menezes- Qu-Vanstone (MQV) protocol [LMQ+03]. KCI-attacks are not only theoretically possible. Hlauschek et al. demonstrated a practical KCI-attack on the TLS protocol in 2015 [HGFS15].

3.2. KCI-Vulnerability in Tox’ AKE

Until now there was no full security analysis conducted neither of the Tox protocol nor its implementation in C. Tox is described as "an experimental cryptographic network library. It has not been formally audited by an independent third party that specializes in cryptography or cryptanalysis. Use this library at your own risk" [Tok18]. The threat model of Tox is still not fully defined (cf. [Sky17]). However Tox’ authenticated key exchange during the handshake is known to be vulnerable to KCI-attacks. This issue was raised on GitHub1 by Jason A. Donenfeld2 (cf. [Don17a]). The vulnerable AKE is currently implemented in the c-toxcore library as outlined in section 2.4. This is the setting for a simplified KCI-attack on the Tox AKE: priv pub • Peer A (Alice) owns the static long-term X25519 key pair {SA ,SA } and has a priv pub session-generated ephemeral X25519 key pair {EA ,EA }. priv pub • Peer B (Bob) owns the static long-term X25519 key pair {SB ,SB } and has a session- priv pub generated ephemeral X25519 key pair {EB ,EB }. priv • Adversary peer M (Mallory) compromised A’s static long-term X25519 private key SA priv pub and has a session-generated ephemeral X25519 key pair {EM ,EM }. Additionally M pub knows B’s static long-term X25519 public key SB . A simplified Tox’ AKE between A and B works like this:

• Message 1 – HandshakeA: A → B

priv pub pub ENC(key = ECDH(SA ,SB ), payload = EA ) (3.1)

• Message 2 – HandshakeB: B → A

priv pub pub ENC(key = ECDH(SB ,SA ), payload = EB ) (3.2)

1Tox Handshake Vulnerable to KCI: https://github.com/TokTok/c-toxcore/issues/426 2Jason A. Donenfeld is the creator of WireGuard VPN: https://www.wireguard.com/

32 Chapter 3. Key Compromise Impersonation and Tox

• Shared session key derivation

priv pub priv pub KAB = KBA = ECDH(EA ,EB ) = ECDH(EB ,EA ) (3.3)

Since M owns A’s static private key and B’s static public key, they can now pretend to be B during the handshake and therefore perform a KCI-attack (again simplified):

• Message 1 – HandshakeM : M → A priv pub pub ENC(key = ECDH(SA ,SB ), payload = EM ) (3.4)

• Message 2 – HandshakeA: A → M priv pub pub ENC(key = ECDH(SA ,SB ), payload = EA ) (3.5)

• Shared session key derivation

priv pub priv pub KAB = KMA = ECDH(EA ,EM ) = ECDH(EM ,EA ) (3.6)

After the handshake A thinks they are talking to B, but are actually talking to M (see detailed description in section 3.4). Therefore an active Man-in-the-Middle attack on A is possible (see detailed description in section 3.5).

3.3. Prerequisites for a KCI-Attack on Tox

To perform a Tox handshake and initiate a crypto connection there are three X25519 key pairs per peer involved: priv pub • A DHT key pair in the cookie phase (e.g. {DHTA , DHTA }) priv pub • A static long-term key pair during the actual AKE (e.g. {SA , SA }) priv pub • An ephemeral key pair (e.g. {EA , EA }) to derive a session key to exchange encrypted messages using symmetric cryptography (i.e. using XSalsa20-Poly1305 in Tox)

Additionally two secret symmetric keys ({kA, kB}) are involved to create the cookies (cf. section 2.4).

The DHT key pairs and secret symmetric keys (kA and kB) involved in the cookie phase of the Tox handshake, make an actual KCI-attack on the Tox’ AKE more complicated than the simplified description from section 3.2. Nevertheless, there are multiple possibilities to actually perform a KCI-attack on a Tox handshake. These will be described in the following. Independently of the chosen attack possibility there are two prerequisites that need to be met by attacker M: priv • M needs to obtain the X25519 static private key SA from A to impersonate B to A pub • M needs to obtain the X25519 static public key from B (SB or B’s Tox ID) to be able to impersonate them to A The options/possibilities to perform a KCI-attack are: 1. M impersonates B to A (see section 3.4) 2. An active MitM attack is possible – M needs to interfere with the handshake packets after the cookie phase (see section 3.5) 3. With DHT keys (hypothetical) – M needs to additionally obtain one DHT secret key of either A or B and the DHT public key of the other peer (see section 3.6)

33 Chapter 3. Key Compromise Impersonation and Tox

3.4. M impersonates B to A using KCI

priv In this attack scenario it’s enough for M to know the static private key of A (SA ) and the pub static public key of B (SB ∈ Tox ID). Additionally A and B need to be online at the same time and need to initiate a handshake by sending cookie request packets. This is necessary in order for M to interfere with the handshake packets after the cookie phase because M doesn’t have the necessary DHT keys to send valid cookie request/response packets on their own. To forge a HandshakeM packet which seems to be coming from B, M needs to intercept and pub decrypt the HandshakeA packet to receive the necessary CookieB, BaseNonceA, EA and OtherCookieA. Also for the HandshakeM packet, M needs to generate an ephemeral key priv pub pair {EM ,EM } and a BaseNonceM . Now M is able to compute the same ephemeral data transport session key as A (KMA = KAM ) and can send valid encrypted messages to A which seem to be coming from their friend B (under the condition that A received HandshakeM to be able to calculate the same shared ephemeral session key). Overall M needs to handle the handshake related packets like this:

• Forward CookieRequestA to B and CookieResponseB to A

• Intercept HandshakeA and don’t forward it to B

• Block all further CookieResponseA and HandshakeA packets

• Block all CookieRequestB and HandshakeB packets • Block all encrypted packets from A to B because they are actually for M The Tox handshake between A and B which is attacked by M using KCI to impersonate B to A is shown in enumeration 3.13. List 3.1.: Tox AKE between peers A and B attacked by adversary M to impersonate B to A

• A: ephemeral X25519 session key pair generation

priv pub {EA ,EA } = GENERATE_KEYPAIR() (3.7)

• A → B: creates and sends cookie request packet CookieRequestA – Intercepted/eavesdropped by M and forwarded to B

pub cookie_request {0x18,DHTA ,NA , cookie cookie_request pub ENC(KAB ,NA , {SA , Padding, echoIDA}, ε), (3.8) cookie_request MACA }

• B → A: creates and sends cookie response packet CookieResponseB – Intercepted/eavesdropped by M and forwarded to A

cookie_response {0x19,NB , cookie cookie_response ENC(KBA ,NB , {CookieB, echoIDA}, ε), (3.9) cookie_response MACB }

3This is simplified and only relevant computations and messages are shown, for the full Tox handshake see enumeration 2.2.

34 Chapter 3. Key Compromise Impersonation and Tox

• A: shared symmetric session key derivation (AKE phase)

handshake handshake priv pub priv pub KAB = KBA = ECDH(SA ,SB ) = ECDH(SB ,SA ) (3.10)

• A → B : creates and sends handshake packet HandshakeA pub – Intercepted and decrypted by M to receive necessary CookieB, BaseNonceA, EA and OtherCookieA, additionally the message is blocked by M and therefore not delivered to B

handshake {0x1a, CookieB,NA , handshake handshake pub ENC(KAB ,NA , {BaseNonceA,EA , (3.11) handshake HASH(CookieB), OtherCookieA}, ε), MACA }

• M: ephemeral X25519 session key pair and BaseNonceM generation (this can be done in advance to speed up the process)

priv pub {EM ,EM } = GENERATE_KEYPAIR() (3.12)

• M: shared ephemeral symmetric session key derivation (data transport phase)

data data priv pub priv pub KMA = KAM = ECDH(EM ,EA ) = ECDH(EA ,EM ) (3.13)

• M: shared symmetric session key derivation (AKE phase)

handshake handshake priv pub priv pub KAB = KBA = ECDH(SA ,SB ) = ECDH(SB ,SA ) (3.14)

• M → A : creates and sends handshake packet HandshakeM

– Crafted by using the relevant data from HandshakeA packet and sent by M to A

handshake {0x1a, CookieA,NM , handshake handshake pub ENC(KAB ,NM , {BaseNonceM ,EM , (3.15) handshake HASH(CookieA), OtherCookieB}, ε), MACM } • A: shared ephemeral symmetric session key derivation (data transport phase)

data data priv pub priv pub KAM = KMA = ECDH(EA ,EM ) = ECDH(EM ,EA ) (3.16)

• M → A: sends encrypted packet EncryptedM

{0x1b, L2B(BaseNonceM + P acket#), data data (3.17) ENC(KMA , BaseNonceM + P acket#, payload, ε), MACM }

• A → M: sends encrypted packet EncryptedA

{0x1b, L2B(BaseNonceA + P acket#), data data (3.18) ENC(KAM , BaseNonceA + P acket#, payload, ε), MACA }

• After both peers, A and M received the encrypted packet, they successfully established a communication channel. A thinks they are talking to B, but are actually talking to M.

35 Chapter 3. Key Compromise Impersonation and Tox

3.5. Active MitM Attack based on KCI

This is the same attack scenario as explained in section 3.4, but in this case M performs a handshake with A by impersonating B and a handshake with B by impersonating A to B (again after a "normal" cookie phase between A and B). The HandshakeA packet contains pub enough information (i.e. CookieB, BaseNonceA, EA and OtherCookieA) for M to send a priv valid handshake packet to both peers. M needs to generate two ephemeral key pairs, {EM1 , pub priv pub EM1} to send to A and {EM2 , EM2} to send to B, and two base nonces (BaseNonceM1 and BaseNonceM2). These will be used to derive session keys with both peers. Therefore M is performing an active Man-in-the-Middle attack by exploiting the KCI- vulnerability in the Tox handshake. M is now able to eavesdrop and modify messages ex- changed between A and B, drop packets or send valid encrypted packets to both peers. Overall M needs to handle the handshake related packets like this:

• Forward CookieRequestA to B and CookieResponseB to A

• Intercept HandshakeA and don’t forward it to B

• Block all further CookieResponseA and HandshakeA packets

• Block all CookieRequestB and HandshakeB packets • Block all encrypted packets from A to B and B to A because they are actually for M The Tox handshake between A and B which is attacked by M by exploiting the KCI- vulnerability to perform an active MitM attack between A and B is shown in enumeration 3.24. List 3.2.: MitM attack from M on Tox’ AKE between peers A and B by exploiting KCI

• A: ephemeral X25519 session key pair generation

priv pub {EA ,EA } = GENERATE_KEYPAIR() (3.19)

• A → B: creates and sends cookie request packet CookieRequestA – Intercepted/eavesdropped by M and forwarded to B

pub cookie_request {0x18,DHTA ,NA , cookie cookie_request pub ENC(KAB ,NA , {SA , Padding, echoIDA}, ε), (3.20) cookie_request MACA }

• B → A: creates and sends cookie response packet CookieResponseB – Intercepted/eavesdropped by M and forwarded to A

cookie_response {0x19,NB , cookie cookie_response ENC(KBA ,NB , {CookieB, echoIDA}, ε), (3.21) cookie_response MACB } • A: shared symmetric session key derivation (AKE phase)

handshake handshake priv pub priv pub KAB = KBA = ECDH(SA ,SB ) = ECDH(SB ,SA ) (3.22) 4This is simplified and only relevant computations and messages are shown, for the full Tox handshake see enumeration 2.2.

36 Chapter 3. Key Compromise Impersonation and Tox

• A → B : creates and sends handshake packet HandshakeA pub – Intercepted and decrypted by M to receive necessary CookieB, BaseNonceA, EA and OtherCookieA, additionally the message is blocked by M and therefore not delivered to B

handshake {0x1a, CookieB,NA , handshake handshake pub ENC(KAB ,NA , {BaseNonceA,EA , (3.23) handshake HASH(CookieB), OtherCookieA}, ε), MACA }

• M: ephemeral X25519 session key pair and BaseNonceM1 generation for HandshakeM1 which will be sent to A (this can be done in advance to speed up the process) priv pub {EM1 ,EM1} = GENERATE_KEYPAIR() (3.24)

• M: ephemeral X25519 session key pair and BaseNonceM2 generation for HandshakeM2 which will be sent to B (this can be done in advance to speed up the process) priv pub {EM2 ,EM2} = GENERATE_KEYPAIR() (3.25) • M: shared ephemeral symmetric session key derivation for communication between M and A (data transport phase)

data data priv pub priv pub KMA = KAM = ECDH(EM1 ,EA ) = ECDH(EA ,EM1) (3.26)

• M: shared symmetric session key derivation for HandshakeM1 and HandshakeM2 (AKE phase)

handshake handshake priv pub priv pub KAB = KBA = ECDH(SA ,SB ) = ECDH(SB ,SA ) (3.27)

• M → A : creates and sends handshake packet HandshakeM1

– Crafted by using the relevant data from HandshakeA packet and sent by M to A

handshake {0x1a, CookieA,NM1 , handshake handshake pub ENC(KAB ,NM1 , {BaseNonceM1,EM1, (3.28) handshake HASH(CookieA), OtherCookieB}, ε), MACM1 }

• M → B : creates and sends handshake packet HandshakeM2

– Crafted by using the relevant data from HandshakeA packet and sent by M to B

handshake {0x1a, CookieB,NM2 , handshake handshake pub ENC(KAB ,NM2 , {BaseNonceM2,EM2, (3.29) handshake HASH(CookieB), OtherCookieA}, ε), MACM2 }

• A: shared ephemeral symmetric session key derivation (data transport phase)

data data priv pub priv pub KAM = KMA = ECDH(EA ,EM1) = ECDH(EM1 ,EA ) (3.30)

37 Chapter 3. Key Compromise Impersonation and Tox

• M → A: sends encrypted packet EncryptedM1

{0x1b, L2B(BaseNonceM1 + P acket#), data data (3.31) ENC(KMA , BaseNonceM1 + P acket#, payload, ε), MACM1 }

• A → M: sends encrypted packet EncryptedA – Message is blocked by M and not delivered to B

{0x1b, L2B(BaseNonceA + P acket#), data data (3.32) ENC(KAM , BaseNonceA + P acket#, payload, ε), MACA } • A now assumes they are talking to B, but are actually connected to M. The connection between M and B is not finished yet. • B: ephemeral X25519 session key pair generation

– After B received HandshakeM2 from M

priv pub {EB ,EB } = GENERATE_KEYPAIR() (3.33) • B: shared ephemeral symmetric session key derivation (data transport phase) data data priv pub priv pub KBM = KMB = ECDH(EB ,EM2) = ECDH(EM2 ,EB ) (3.34) • B: shared symmetric session key derivation (AKE phase) handshake handshake priv pub priv pub KBA = KAB = ECDH(SB ,SA ) = ECDH(SA ,SB ) (3.35)

• B → M : creates and sends handshake packet HandshakeB

– Message is intercepted and decrypted by M to receive necessary BaseNonceB and pub EB , additionally the message is blocked by M and therefore not delivered to A

handshake {0x1a, CookieA,NB , handshake handshake pub ENC(KBA ,NB , {BaseNonceB,EB , (3.36) handshake HASH(CookieA), OtherCookieB}, ε), MACB } • M: shared ephemeral symmetric session key derivation for communication between M and B (data transport phase) data data priv pub priv pub KMB = KBM = ECDH(EM2 ,EB ) = ECDH(EB ,EM2) (3.37)

• B → M: sends encrypted packet EncryptedB – Message is blocked by M and not delivered to A

{0x1b, L2B(BaseNonceB + P acket#), data data (3.38) ENC(KBM , BaseNonceB + P acket#, payload, ε), MACB }

• M → B: sends encrypted packet EncryptedM2

{0x1b, L2B(BaseNonceM2 + P acket#), data data (3.39) ENC(KMB , BaseNonceM2 + P acket#, payload, ε), MACM2 } • M is now able to eavesdrop and modify messages exchanged between A and B, drop packets or send valid encrypted packets to both peers.

38 Chapter 3. Key Compromise Impersonation and Tox

3.5.1. Proof of Concept Attack Program to demonstrate a KCI-Attack

It was planned to create a proof of concept (PoC) attack program to demonstrate a KCI- attack on toxcore. Due to the complexity of creating a modified MitM-version of toxcore to be able to exploit KCI, it was favored to first implement a new Noise-based Tox handshake which is KCI-resilient. The implementation of this new Noise-based handshake was also sophisticated (see chapter 4 for details). Therefore the creation of a PoC attack program could not be completed for this thesis and is postponed to future work. To implement a PoC attack program it is necessary to create a custom "MitM-capable" Tox client (hereafter referred to as MitM-application). This MitM-application needs to be based on a modified MitM-toxcore library. Besides that, M needs to control the network between A and B to be able to intercept and drop packets. Additionally M needs to know the IP addresses of A and B to identify the relevant Tox packets. The following enumeration outlines requirements for this MitM-application and necessary toxcore adaptations: priv • MitM-application initializes a MitM-toxcore instance by using SA • MitM-toxcore instance is initialized without Tox friends (by default when using only secret key) • MitM-toxcore shouldn’t announce itself in the DHT because otherwise e.g. B will try to initiate a connection to M and not the real A. This would be unsuccessful since M’s MitM-toxcore instance has no friendship with B, but it will likely mess up the DHT priv pub state when two peers announce with the same static key pair (i.e. {SA , SA }). If and how this is possible would require detailed understanding of toxcore’s DHT module. • The MitM-application needs to be able to trigger MitM-toxcore’s Net_crypto functions based on the intercepted HandshakeA packet (Net_crypto’s handshake/AKE functions are described in more detail in section 4.2):

– After HandshakeA was received, the handle_crypto_handshake() function needs to be called.

∗ This function needs to be adapted because MitM-toxcore can’t verify CookieB (it doesn’t have the necessary kB to decrypt it). pub ∗ Access to SB inside handle_crypto_handshake() is needed. This is handshake necessary because B (i.e. the real recipient) would calculate KAB = priv pub pub ECDH(SB , SA ) by extracting SA from their own cookie to decrypt the handshake packet. M and therefore the attack application needs to be able handshake priv pub to calculate KAB = ECDH(SA ,SB ) instead. ∗ The MitM-application needs to save CookieA and CookieB to use it afterwards to create and send HandshakeM2 packet to B. – The handle_crypto_handshake() function is called in handle_new_con nection_handshake() which is called in udp_handle_packet() which is called via a callback. Hence in the normal toxcore library this is triggered automat- ically if a handshake packet is received via UDP. Therefore a way must be found to trigger handle_crypto_handshake() with a packet that was intended to be received by another toxcore instance. ∗ Additionally handle_new_connection_handshake() needs to be adapted, pub because DHTA is unknown and therefore cannot be verified by the MitM- toxcore. – After handle_crypto_handshake() is finished, accept_crypto_connect ion() is called in handle_new_connection_handshake() (again via a call-

39 Chapter 3. Key Compromise Impersonation and Tox

back). This function creates a new Crypto_Connection object5 for the connec- tion between M and A. priv pub ∗ In accept_crypto_connection() BaseNonceM1 and {EM1 ,EM1} get data generated and KMA gets calculated. Further the connection state is set to accepted (CRYPTO_CONN_NOT_CONFIRMED). ∗ It would be necessary to adapt create_send_handshake and create_cr ypto_handshake() to pass CookieA and CookieB (or to generate random bytes instead of CookieB) to these functions. These cookies will then be sent with HandshakeM1 to A. – Then MitM-toxcore starts to exchange encrypted packets between M and A. Now there is a successful Tox connection and A thinks they are talking to B, but are actually talking to M. • To also create a Tox connection to B it is necessary to implement an adapted new_cryp to_connection() function. This is required to be able to create a Tox connection to B without sending a cookie request packet. Instead MitM-toxcore sends HandshakeM2 packet by using the information received from HandshakeA (i.e. CookieA and CookieB). – The new_crypto_connection() function is called via a callback if two peers are friends. It needs to be investigated how to trigger it otherwise.

– When the MitM-application receives the HandshakeB packet, it again needs access pub to SB in handle_crypto_handshake(). – Then MitM-toxcore starts to exchange encrypted packets between M and B. Now there is a successful Tox connection and B thinks they are talking to A, but are actually talking to M. • M using this MitM-application needs to pass messages between A and B manually because there are now two completely separate connections. Another possibility is to implement functionality to pass/block/insert messages automatically between these two Tox connections. This means in order to implement a MitM-toxcore library deeper understanding of the Tox protocol and its toxcore implementation is necessary. It is not enough to adapt the Net_crypto module.

3.6. KCI-Attack with DHT Keys

Note that this is a hypothetical attack scenario because it is necessary for an attacker M to either compromise keys of both peers or compromise the DHT private key of A while being a Tox-friend of B. If M also compromises B it is not a KCI-attack anymore because the "advantage" of KCI is that it is not necessary to compromise the party that should be impersonated. priv In this MitM attack scenario it’s necessary for M to know the static private key of A (SA ) pub and the static public key of B (SB ∈ Tox ID). Additionally A and B need to be online at the same time to have valid DHT key pairs. This is necessary in order for M to compromise one DHT private key (from A or B) and retrieve the DHT public key of the other peer. M can look up the DHT public key in the DHT if M is a Tox friend of this party, otherwise it’s priv pub necessary to compromise the DHT public key of this party. With e.g. DHTA and DHTB

5"Object" in this case is used to denote a concrete instances of a C struct and is therefore not an object in an object-oriented programming sense.

40 Chapter 3. Key Compromise Impersonation and Tox

M is able to send a CookieRequestMB to A which seems to be sent by B. After receiving CookieResponseA, M is able to forge a HandshakeM packet which seems to be coming from

B, by using CookieA and crafting OtherCookieMB . To craft OtherCookieMB M needs to generate a secret symmetric key kM . Also for the HandshakeMB packet, M needs to generate priv pub an ephemeral key pair {EM ,EM } and a BaseNonceM . Afterwards M needs to intercept pub and decrypt the HandshakeA packet to receive the necessary EA to compute the shared session key. Again, M can send valid encrypted messages to A which seem to be coming from

B. Alternatively, M could send a CookieResponseMB in this setting, instead of sending a

CookieRequestMB . Overall M needs to handle the handshake related packets between A and B like this:

• Intercept and block all CookieRequestA, CookieResponseA, HandshakeA and EncryptedA packets A sends to B

• Block all CookieRequestB, CookieResponseB, HandshakeB and EncryptedB packets B sends to A This attack scenario has the disadvantage that it’s necessary to compromise an additional DHT private key. Also DHT key pairs are not permanent because they are renewed every time a Tox instance (e.g. a client) is closed or restarted. Although for long running clients they currently do not change often.

41 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

In the previous chapter the KCI-vulnerability in Tox’ current handshake was described. By using the Noise Protocol Framework a new KCI-resistant Tox handshake was designed and implemented based on the Noise IK handshake pattern. This chapter shows the exact calcu- lations performed when using Noise IK to establish a shared secret session key between two parties. Afterwards two implementation approaches are presented. The first implementation uses the ChaCha20-Poly1305 cipher during the handshake and also for encryption during the transport phase. This approach has the disadvantage that it can’t handle UDP packet loss. The final implementation uses ChaCha20-Poly1305 during the handshake and XSalsa20- Poly1305 (Tox primary cipher) for transport phase encryption and works with packet loss.

4.1. Design of a KCI-resistant Tox Handshake based on the Noise IK Pattern

As the objective of thesis is to design a new Tox handshake which is KCI-resistant and provides strong forward secrecy, the underlying Noise handshake pattern needs to provide payload authentication property #2 and payload confidentiality property #5 (cf. section 2.5.3). At first it was considered that both static long-term public keys are known in advance (i.e. exchanged out-of-band) in the Tox protocol, for that reason it was intended to use the Noise KK pattern. In fact it was discovered that this is only true for the initiator of a Tox handshake (i.e. the peer sending a cookie request packet), but not for the responder. As per the design of the Tox handshake, the responder retrieves the static public key of the initiator from their own cookie, which he receives with the handshake packet of the initiator. This is not compatible with the Noise KK pattern, because to be able to receive a handshake packet it is necessary to first initialize a handshake state with both peers static keys. The static public key of the initiator is included in the cookie request packet, but the peer receiving such a packet mustn’t allocate any memory to prevent DoS (see section 4.2.2 for more details). Therefore the implementation was adapted to use the Noise IK pattern (see sections 4.3 and 4.4 for implementation details). In regard to KCI-resistance there is no difference between the KK and IK pattern because both provide the same security properties. The security properties for all IK message patterns are listed in table 4.1 (for the meaning of the values listed in "Authentication" and "Confidentiality" columns see section 2.5.3). The security properties for the handshake messages (number one and two) payloads are weaker than the final security properties achieved by transport payloads (messages three and four). Both handshake messages don’t provide strong forward secrecy, but the transport messages do. For that reason these early must be used with caution. Transport payloads are shown as arrows without a pattern. These transport payloads are listed explicitly in the IK pattern because they have different security properties than the previous handshake

42 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise payload sent from the same party. In case of the Noise IK pattern, the security properties of the second transport message (message four) only apply if message three was received by the responder. The payload of message one only provides authentication property #1 which means that it is vulnerable to KCI. An attacker, who is in possession of the static secret key from the receiver, could forge this message (cf. section 2.5.3). However, the initiator is authenticated with the first transport payload sent by them. Therefore it’s not possible for an attacker to successfully establish an encrypted connection to the receiver. To be able to do so, an attacker would need to compromise both static private keys to impersonate an involved party to the other (cf. authentication property #2). All transport messages are KCI-resistant. Noise patterns starting with I have the caveat that the responder is only guaranteed weak forward secrecy for their own transport messages, until they receive a transport message from the initiator. Afterwards the responder becomes assured of strong forward secrecy. For the Noised-based Tox handshake this means that the responder has to wait for the first transport message from the initiator before they actually start sending data. Strictly speaking, this means that the key exchange phase is not 1-RTT (as the responder cannot safely send data to the initiator until they have received a verified data transport message from the initiator), but actually 1.5-RTT. This is also the case for the Noise-based handshake implemented in WireGuard (cf. [Don17b] and [Wu19]).

# Message pattern Authentication Confidentiality <- s ... 1 -> e, es, s, ss 1 2 2 <- e, ee, se 2 4 3 -> 2 5 4 <- 2 5

Table 4.1.: Noise IK handshake pattern’s payload security properties (cf. [Per18] and section 2.5.3)

Besides the payload security properties each Noise pattern is also assigned an identity- hiding property in regard to the confidentiality supplied to the static public keys (of both initiator and responder). Noise only considers identity leakage through the static public key field in the handshake and not through other means (e.g. payload fields, metadata such as IP addresses or traffic analysis). In the Noise IK pattern the static key of the initiator is sent encrypted in message #1 by hashing the responder’s static public key, but without forward secrecy. Therefore, if an attacker would learn the responder’s static private key they can decrypt the initiator’s static public key (cf. identity hiding property #4 in [Per18]). The static public key of the responder is not transmitted, but a passive attacker can check candidates priv for the responders static private key (SB ) and determine whether the candidate is correct. An attacker could also replay a previously recorded message #1 to a new responder and determine whether the two responders are the same (i.e. are using the same static key pair) by whether the recipient accepts the message (cf. identity hiding property #3 in [Per18]). Therefore the Noise IK pattern also provides deniability as a property.

4.1.1. Execution of the Noise IK Handshake Pattern

This section will describe the exact computations performed during the Noise IK handshake pattern as used in Tox (cf. figure 2.16 resp. table 4.1). As outlined in section 2.5.1 a handshake pattern is not a complete Noise protocol. The full

43 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise name of the Noise protocol used for the Tox handshake is Noise_IK_25519_ChaChaPoly_SHA512. Therefore this Noise protocol is based on the X25519 DH function, the ChaCha20-Poly1305 cipher function and the SHA512 hash func- tion. ChaCha20-Poly1305 is used as AEAD cipher instead of XSalsa20-Poly1305 (the cipher used in Tox) because XSalsa20 is currently not supported by the Noise specification (see section 2.5.2 for supported cryptographic primitives). Additionally Noise is specified to use 8-byte nonces and doesn’t support 24-byte nonces that are required by XSalsa20. X25519 respectively SHA512 were chosen because these primitives are already used extensively in the toxcore implementation. Note that the cookie phase of the Tox handshake is the same as described in section 2.4. The AKE phase is now based on the Noise IK pattern and during the data transport phase two keys are used for symmetric encryption instead of one. The following enumeration shows the notation used for (cryptographic) values and opera- tions in chapter 4: priv pub • SA ,SA : X25519 static long-term private and public keys of a peer A (32 byte each) priv pub • EA ,EA : X25519 ephemeral private and public keys of a peer A (32 byte each) send recv send • TA ,TA : Two 32-byte symmetric cipher keys used by peer A – TA is used to recv send encrypted messages and TA to decrypt received messages • n: 8-byte (64-bit) unsigned integer counter-based nonce value • h: 64-byte SHA512 handshake hash • ck: 32-byte chaining key • k: 32-byte cipher key, which may be empty; Empty indicates that k has not yet been initialized

• BaseNonceA: 24-byte random nonce value generated by peer A

• CookieA, OtherCookieA: 112-byte cookie created by peer A • ECDH(private_key, public_key): X25519 ECDH computation of a 32-byte shared secret key given a 32-byte secret key and a 32-byte public key (cf. [LHT16]) • ENC(key, nonce, plaintext, ad): ChaCha20-Poly1305 AEAD encryption of an ar- bitrary length plaintext with a 256-bit key and a 64-bit counter-based nonce, returns a ciphertext and a 16-byte authentication tag; Arbitrary length associated data ad is authenticated together with cipertext, but may be empty • DEC(key, nonce, ciphertext, ad): ChaCha20-Poly1305 AEAD decryption of arbi- trary length ciphertext with a 64-bit counter-based nonce, verifies the 16-byte authen- tication tag and returns a plaintext; Arbitrary length associated data ad must be the same as during encryption, but may be empty

• MACA: Message authentication code – 16-byte authentication tag calculated by ENC() and DEC() • HASH(input): SHA512(input), returns 64-byte SHA512 hash of input • GENERATE_KEYPAIR(): Returns a new X25519 key pair • KDF(chaining_key, input_key_material, num_outputs): HKDF construction (cf. [KE10]) based on HMAC-SHA512 using chaining_key as salt to generate a specified number of output keys (num_outputs) • ε: Empty string

44 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

Some tokens are interpreted differently by the initiator and the responder. These differences are prefixed with "I:" for the initiator and "R:" for the responder. The handshake computations start with hashing the Noise protocol name and prologue (which is also the protocol name in case of Tox):

1: h0 = HASH("Noise_IK_25519_ChaChaPoly_SHA512")

2: ck0 = h0

3: h1 = HASH(h0k"Noise_IK_25519_ChaChaPoly_SHA512"), n = 0

Afterwards the pre-message is processed as follows: • <- s: pre-message from B to A pub – s: A pre-message from the responder to the initiator. Static public key SB was previously exchanged out-of-band.

pub 4: h2 = HASH(h1kSB )

• -> e, es, s, ss: Message #1 sent from A to B – e: The initiator generates a fresh ephemeral X25519 key pair and sends the re- pub sulting public key EA to the responder by adding it as cleartext into the message buffer. The public key gets hashed along with the old h to derive a new h.

priv pub pub 5: I: {EA ,EA } = GENERATE_KEYPAIR(); publish EA pub R: Read EA pub 6: h3 = HASH(h2kEA )

priv pub pub – es: The initiator computes ECDH(EA , SB ) and the responder ECDH(EA , priv SB ). This results in the same shared secret and authenticates the receiver (but not the sender).

priv pub 7: I: (ck1, k0) = KDF(ck0, ECDH(EA ,SB ), 2), n = 0 priv pub R: (ck1, k0) = KDF(ck0, ECDH(SB ,EA ), 2), n = 0

pub – s: The initiator sends their encrypted static public key SA to the responder. If the responder is not able to decrypt the ciphertext, they abort the handshake.

pub 8: I: enc pub = ENC(k0, n, SA , h3); publish enc pub SA SA pub R: SA = DEC(k0, n, enc pub , h3); abort on failure SA

9: h4 = HASH(h3kenc pub ) SA

priv pub – ss: The initiator computes ECDH(SA , SB ) and the responder computes the priv pub same shared secret using ECDH(SB , SA ).

priv pub 10: I: (ck2, k1) = KDF(ck1, ECDH(SA ,SB ), 2), n = 0 priv pub R: (ck2, k1) = KDF(ck1, ECDH(SB ,SA ), 2), n = 0

45 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

After all tokens were processed, an (possibly empty) application chosen payload m0 is appended to the handshake message buffer and encrypted using k1. If the responder fails to decrypt c0, it aborts the handshake. In Tox, the payload m0 consists of a 24-byte BaseNonceA (if based on XSalsa20 cipher, see section 4.4 for details), a 64-byte SHA512 hash of the CookieB sent unencrypted with the same packet (outside of the Noise payload) and the 112-byte OtherCookieA.

11: I: c0 = ENC(k1, n, m0, h4); publish c0

R: m0 = DEC(k1, n, c0, h4); abort on failure

12: h5 = HASH(h4kc0)

• <- e, ee, se: Message #2 sent from B to A – e: The responder generates a fresh ephemeral X25519 key pair and sends the pub resulting public key EB to the initiator by adding it as cleartext into the message buffer. The public key gets hashed along with the old h to derive a new h.

priv pub pub 13: R: {EB ,EB } = GENERATE_KEYPAIR(); publish EB pub I: Read EB pub 14: h6 = HASH(h5kEB )

priv pub priv – ee: The responder computes ECDH(EB , EA ) and the initiator ECDH(EA , pub EB ). This again results in the same shared secret.

priv pub 15: R: (ck3, k2) = KDF(ck2, ECDH(EB ,EA ), 2), n = 0 priv pub I: (ck3, k2) = KDF(ck2, ECDH(EA ,EB ), 2), n = 0

priv pub priv – se: The responder computes ECDH(EB , SA ) and the initiator ECDH(SA , pub EB ). This results in the same shared secret.

priv pub 16: R: (ck4, k3) = KDF(ck3, ECDH(EB ,SA ), 2), n = 0 priv pub I: (ck4, k3) = KDF(ck3, ECDH(SA ,EB ), 2), n = 0

After all tokens were processed an (possibly empty) application chosen payload m1 is ap- pended to the handshake message buffer and encrypted using k3. If the initiator fails to de- crypt c1, it aborts the handshake. In Tox, the payload m1 consists of a 24-byte BaseNonceB (if based on XSalsa20 cipher, see section 4.4 for details), a 64-byte SHA512 hash of the CookieA sent unencrypted with the same packet (outside of the Noise payload) and the 112-byte OtherCookieB.

17: R: c1 = ENC(k3, n, m1, h6); publish c1

I: m1 = DEC(k3, n, c1, h6); abort on failure

18: h7 = HASH(h6kc1)

46 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

A successful handshake is finished by deriving symmetric session keys for payload encryp- tion during the data transport phase. This is done by hashing the chaining key once more with ε. Both keys are actually the same for both parties, but the sending key is the receiving key of the other party.

send recv 19: I: {TA ,TA } = KDF(ck4, ε, 2), n = 0 recv send R: {TB ,TB } = KDF(ck4, ε, 2), n = 0

The resulting 32-byte (256 bit) symmetric session keys can be used to encrypt messages using the ChaCha20-Poly1305 or the XSalsa20-Poly1305 AEAD stream cipher. The imple- mentation using ChaCha20 is described in section 4.3 and the implementation using XSalsa20 is described in section 4.4. Theoretically also other ciphers could be used during the data transport phase, if they support symmetric keys with less or equal to 256-bit. ChaCha20 and XSalsa20 were chosen because the former is supported by Noise and the latter is already used in toxcore extensively. In short the Noise-based AKE designed for the Tox handshake provides the following advantages (cf. section 2.4.1): • Based on a formally verified construction (instead of a "home-brewed" protocol) • Keys used for symmetric encryption are derived using HKDF instead of using plain X25519 DH results • Forward secrecy • Avoids KCI • Key confirmation • Identity hiding (deniability) • Authenticated E2EE • Replay-attack prevention, while allowing for network packet reordering • Modern cryptographic primitives: X25519, ChaCha20/XSalsa20, Poly1305, SHA512

4.1.2. Adapted Tox Protocol Packets

The cookie phase and therefore also the cookie request/response messages are unchanged with the Noise-based Tox handshake. Due to the use of the Noise IK pattern (as described in section 4.1) the messages sent by initiator and responder are different in the AKE phase. The initiator sends their ephemeral public key and their encrypted static public key (see figure 4.1). The responder sends only their ephemeral public key (see figure 4.2). The figures 4.1 and 4.2 show the handshake packets sent during the Noise-based AKE. The BaseNonceA needs to be included if XSalsa20-Poly1305 is used to send encrypted messages (see section 4.4). If ChaCha20-Poly1305 is used to send encrypted messages, the payload is sent without BaseNonce (see section 4.3).

47 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

0x1a (1 byte packet kind)

CookieB (112 bytes) pub EA (32 bytes) o pub enc pub (32 bytes) Encrypted S SA A

enc MACA (16 bytes)

 BaseNonce (24 bytes)  A  HASH(CookieB) (64 bytes) Encrypted payload c0  OtherCookieA (112 bytes) 

c0 MACA (16 bytes)

Figure 4.1.: Noise-based handshake packet from initiator A (XSalsa20-based transport phase; 409 bytes)

0x1a (1 byte packet kind)

CookieA (112 bytes) pub EB (32 bytes)  BaseNonce (24 bytes)  B  HASH(CookieA) (64 bytes) Encrypted payload c1  OtherCookieB (112 bytes) 

c1 MACB (16 bytes)

Figure 4.2.: Noise-based handshake packet from responder B (XSalsa20-based transport phase; 361 bytes)

4.2. Implementation Overview of the Noise IK based Tox Handshake

Table 4.2 lists all the software that was used to implement the Noise-based Tox handshake, including their version, website and a short description. The Noise-based AKE during the Tox handshake was implemented by adopting the necessary functions in c-toxcore and by using the functions supplied by the Noise-C library. The Noise-C library is a plain C imple- mentation of the Noise protocol framework from Rhys Weatherley. Cryptographic operations are implemented in toxcore by using functions provided by the libsodium library. Minitox, which is a minimal client for Tox, was used to test the handshake behavior. Flakynet was used to test UDP packet loss during a Tox connection. In appendix A.3 to A.5 it is described how to build the different libraries and also minitox respectively flakynet.

48 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

Software/ Version/ Website Short description Library Commit ID c-toxcore e671490 https://github.com/ This is Tox’ implementa- (12.03.2020) goldroom/c-toxcore (forked tion in C. The Noise-based from https://github.com/ handshake is added to c- TokTok/c-toxcore) toxcore. Build info: appendix A.5 libsodium 1.0.18- https://doc.libsodium. Sodium is a software li- stable org/ brary for encryption, de- cryption, signatures, pass- word hashing and more. This is toxcore’s depen- dency for cryptographic primitives. Build info: appendix A.3 Noise-C a5250fa https://github.com/ A plain C implementation (17.04.2019) goldroom/noise-c (forked of the Noise framework. from https://github.com/ Noise-C is used to im- rweather/noise-c); https: plement the KCI-resistant //rweather.github.io/ handshake in toxcore. noise-c/index.html Build info: appendix A.4 minitox 20d96854 https://github.com/ A minimal client for Tox. (23.11.2018) goldroom/minitox (forked Minitox is used to test Tox from https://github.com/ handshake behavior. hqwrong/minitox) Build info: appendix A.5.2 flakynet 029d806 https://github.com/ A simple LD_PRELOAD (06.05.2020) TokTok/toktok-stack/ wrapper dropping blob/master/tools/ UDP packets sent via debug/flakynet.c sendto(). Flakynet is used to test packet loss behavior of toxcore. Build info: appendix A.5.3

Table 4.2.: Software and libraries used to implement and test the Noise-based Tox handshake

49 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

The first approach to implement a Noise-based handshake was to use the Noise KK pattern, which wasn’t possible due to the patterns incompatibility with the c-toxcore implementation (see section 4.1.1 for details). This is why the handshake was adopted based on the Noise IK pattern. The Noise IK pattern was realized in two different approaches. The first approach was implemented using ChaCha20 during the AKE phase of the handshake and also during the data transport phase because Noise doesn’t support XSalsa20 (and is therefore also not supported by Noise-C). This solution works only if no encrypted data packets are lost (see detailed description in section 4.3). The second approach represents a solution to the packet loss problem. Two functions were added to the Noise-C library to retrieve the symmetric keys send recv (TA ,TA ). These keys are then used to successfully send XSalsa20-encrypted packets. This enabled the usage of the already-existing UDP packet loss handling functionality of toxcore (for details see section 4.4). The following enumeration lists all the git1 repositories respectively branches and their purpose during the implementation phase of this thesis. • Repository: goldroom/c-toxcore, Branch: tb_noise_handshake – Unsuccessful attempt to implement Noise KK pattern in toxcore; would require fundamental changes to the Tox protocol and toxcore implementation (out-of-scope for this thesis) – URL to branch: https://github.com/goldroom/c-toxcore/tree/tb_ noise_handshake – Latest commit ID: e4ced054 (01.07.2020) • Repository: goldroom/c-toxcore, Branch: tb_noise_handshake_IK – Successful approach to implement Noise IK pattern in toxcore using the ChaCha20- Poly1305 cipher during AKE and data transport phase; Implementation cannot handle UDP packet loss; no decryption is possible at the receiving peer if one encrypted packet is lost (which is very likely to happen) – URL to branch: https://github.com/goldroom/c-toxcore/tree/tb_ noise_handshake_IK – Latest commit ID: c65babde (01.07.2020) • Repository: goldroom/c-toxcore, Branch: tb_noise_handshake_IK_noise_patch – Successful approach to implement Noise IK pattern in toxcore using the ChaCha20 cipher during the AKE and XSalsa20 during data transport phase; Implementation is able to handle UDP packet loss – URL to branch: https://github.com/goldroom/c-toxcore/tree/tb_ noise_handshake_IK_noise_patch – Latest commit ID: 43536dc7 (01.07.2020) ∗ Repository: goldroom/noise-c, Branch: split_key_patch · Two functions were added to the Noise-C library to retrieve symmetric send recv encryption keys (TA ,TA ) after a successful handshake; This is nec- essary to be able to use the keys for encryption with XSalsa20 instead of ChaCha20 · URL to branch: https://github.com/goldroom/noise-c/tree/ split_key_patch · Latest commit ID: 50f9631 (01.07.2020)

1https://git-scm.com/

50 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

• Repository: goldroom/minitox, Branch: tb_minitox_adaptions – A minimal client for Tox; Functions to print Tox ID, static long-term private key, DHT private key and DHT public key of the Tox instance at startup were added – URL to branch: https://github.com/goldroom/minitox/tree/tb_minitox_ adaptions – Latest commit ID: 22fd575 (01.07.2020) The Tox handshake, including the AKE, is implemented in toxcore/net_crypto.c (corre- sponding header file is toxcore/net_crypto.h). Only these two files were changed to imple- ment the new Noise-based handshake and the rest can remain unchanged. There are two structs that are very important in regard to the handshake, Crypto_Connection and New_Connection. The struct Crypto_Connection (see listing 4.1) is used to save con- nection information between two peers. The Crypto_Connection object2 is called conn and contains the static public key of the remote peer, the base nonces of both peers, the ephemeral session key pair of the local peer, the ephemeral session public key of the remote peer, the shared session key, the status of this connection, the DHT public key of the remote peer and more.

1 typedef struct Crypto_Connection { 2 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The static public key of the peer. */ 3 uint8_t recv_nonce[CRYPTO_NONCE_SIZE];/ * Base nonce of received packets. */ 4 uint8_t sent_nonce[CRYPTO_NONCE_SIZE];/ * Base nonce of sent packets. */ 5 uint8_t sessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE];/ * Our ephemeral public key for this session. */ 6 uint8_t sessionsecret_key[CRYPTO_SECRET_KEY_SIZE];/ * Our ephemeral private key for this session. */ 7 uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The ephemeral session public key of the peer. */ 8 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];/ * The precomputed ephemeral shared key from encrypt_precompute. */ 9 Crypto_Conn_State status;/ * See Crypto_Conn_State documentation */ 10 uint64_t cookie_request_number;/ * Number used in the cookie request packets for this connection(echoID!) */ 11 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The dht public key of the peer */ 12 [...] 13 } Crypto_Connection; Listing 4.1: Crypto_Connection struct as defined in net_crypto.c

The struct New_Connection (see listing 4.2) is used if a handshake packet from a peer is received, for whom no Crypto_Connection exists yet. The information from the hand- shake packet is temporarily saved in a New_Connection object (e.g. static public key, base nonce, DHT public key etc.) and afterwards used to create the Crypto_Connection object.

2"Objects" in this chapter is used to denote concrete instances of C structs and therefore are not objects in an object-oriented programming sense.

51 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

1 typedef struct New_Connection { 2 IP_Port source; 3 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The static public key of the peer. */ 4 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The dht public key of the peer. */ 5 uint8_t recv_nonce[CRYPTO_NONCE_SIZE];/ * Base nonce of received packets. */ 6 uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The ephemeral public key of the peer. */ 7 uint8_t *cookie; 8 uint8_t cookie_length; 9 } New_Connection; Listing 4.2: New_Connection struct as defined in net_crypto.h

The HANDSHAKE_PACKET_LENGTH is defined as shown in listing 4.3 (cf. figure 2.11).

1 #define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE) Listing 4.3: HANDSHAKE_PACKET_LENGTH as defined in net_crypto.c (385 bytes)

These are the relevant functions for the handshake/AKE that need to be adapted (ordered by appearance in net_crypto.c): • create_crypto_handshake(): This function creates a crypto handshake packet of HANDSHAKE_PACKET_LENGTH size (used by both involved parties). It is called by create_send_handshake(). • handle_crypto_handshake(): This function handles an incoming handshake packet. The peer opens the cookie to verify if it’s theirs. The encrypted part of the packet is decrypted. The decrypted hash of the cookie is compared to the calculated hash of the cookie sent in cleartext. If this is a valid handshake packet, the information contained is copied to the Crypto_Connection object (e.g. base nonce, ephemeral session public key etc.). It is called by handle_new_connection_handshake() and handle_packet_connection(). • send_data_packet(): This function creates and sends an encrypted data packet to the remote peer. It uses the base nonce (of the peer that wants to send the packet) and the shared session key (calculated from both peers ephemeral session keys) to encrypt the payload by using XSalsa20-Poly1305. • handle_data_packet(): This function handles an incoming encrypted data packet. It uses the base nonce (of the peer that sent the packet) and the shared session key (calculated from both peers ephemeral session keys) to decrypt the payload by using XSalsa20-Poly1305. • create_send_handshake(): This function calls create_crypto_handshake() to create a handshake packet and sends it to the remote peer. It is called by accept_crypto_connection(), handle_new_connection_handshake() and handle_packet_connection(). • handle_packet_connection(): This function is called whenever a packet is re- ceived via UDP or TCP (except cookie request packets). Depending on the kind of packet received, a cookie response packet, a crypto handshake packet or a crypto data packet is handled. If necessary the connection state is updated and a handshake packet is sent in return. • handle_new_connection_handshake(): This function is called when a hand- shake packet is received from a peer, for whom no Crypto_Connection object was

52 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

created yet. The information from the handshake packet is temporarily saved into a New_Connection object and afterwards used to create a Crypto_Connection for this peer. Therefore the peer calling this function is responding to a handshake. This function is used to set the role for the Noise-based handshake to responder. • accept_crypto_connection(): This function is called via handle_new_conne ction_handshake() if this peer didn’t start to initiate a crypto connection themself (i.e. by calling new_crypto_connection()). A Crypto_Connection object is created by using the information from a New_Connection object, by generating a base nonce and an ephemeral session key pair, by calculating the ephemeral shared session key and more. An handshake packet is sent as a response. • new_crypto_connection(): A peer calling this function is initiating a handshake by creating a Crypto_Connection object, by generating a base nonce and an ephemeral session key pair and by sending a cookie request packet. This function is used to set the role for the Noise-based handshake to initiator.

4.2.1. Using Noise-C to implement a Noise Protocol

The Noise-C library "is a plain C implementation of the Noise Protocol, intended as a refer- ence implementation". The project website states that "this project is still a work in progress. There is still a lot of cleaning up and example writing to do". The initial target is GNU/ systems but the library is also usable on macOS 10.15.3/Catalina. It is based on Noise spec- ification revision 30 (current revision is 34) and supports most Noise handshake patterns, including KK and IK. The project includes a client/server echo example which was used to learn how to use the library. [Wea16]

4.2.2. Implementation Approach based on Noise KK Pattern

As explained in section 2.4 in the current handshake both peers can be initiator and respon- der at the same time (cf. figure 2.14). In the Noise-based handshake it needs to be defined which peer is initiator and which is responder. Depending on the role different calculations are performed and therefore different functions are called. It was tried to handle this dif- ferentiation by adapting the existing handshake implementation in net_crypto.c as little as possible. A handshake is initiated by calling new_crypto_connection(), therefore this function sets the role of this peer to initiator. A peer is responding to a received handshake packet by calling handle_new_connection_handshake(), therefore this function sets the role of this peer to responder. In the current Tox handshake, the responder retrieves the static public key of the initiator from the handshake packet (i.e. by calling handle_crypto_handshake()). This is not compatible with the Noise KK pattern because to retrieve data from a Noise-based handshake packet, it is necessary to initialize the NoiseHandshakeState beforehand with the static keys (that were exchanged via pre-messages). Therefore the static public key of the initiator must be known before calling handle_crypto_handshake(), which it isn’t. The static public key from the initiator is contained in the cookie request packet, but, as mentioned in section 2.4, the responder shouldn’t allocate memory for received cookie request packets to prevent DoS. Therefore the Tox handshake would need to be completely redesigned to be compatible with the Noise KK pattern. Instead, the Noise-based handshake was implemented using the IK pattern, which includes the static public key of the initiator in a handshake

53 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

message. Hence, to initialize the NoiseHandshakeState of the responder, it’s enough for the responder to know their own static private key (see section 4.3 for details).

4.3. Implementation Approach with ChaCha20-Poly1305 during the AKE and the Transport Phase

This section describes the implementation approach by using the Noise-C library in the AKE phase of the handshake and for encryption/decryption in the data transport phase. Since Noise doesn’t support the XSalsa20 stream cipher, this implementation approach uses ChaCha20 during the AKE and also during the transport phase. As a first step, the header file of the Noise-C library is included and the full Noise protocol is defined as string in net_crypto.h (see listing 4.4).

1 #include 2 [...] 3 #define CRYPTO_NOISE_PROTOCOL_NAME"Noise_IK_25519_ChaChaPoly_SHA512" Listing 4.4: Include Noise-C header file and definition of CRYPTO_NOISE_PROTOCOL_NAME in net_crypto.h

A NoiseHandshakeState object (containing the variables necessary for the handshake) send recv and two NoiseCipherState objects (containing TA resp. TA and n) were added to the Crypto_Connection struct (see listing 4.5, cf. listing 4.1). The base nonces are not needed anymore because they are included in the NoiseCipherState objects. The session keys are handled via the NoiseHandshakeState object.

1 typedef struct Crypto_Connection { 2 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The static public key of the peer. */ 3 // Shared_key is still used in the cookie phase(DHT-based shared_key) 4 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];/ * The precomputed ephemeral shared key from encrypt_precompute. */ 5 Crypto_Conn_State status;/ * See Crypto_Conn_State documentation */ 6 uint64_t cookie_request_number;/ * Number used in the cookie request packets for this connection(echoID!) */ 7 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The dht public key of the peer */ 8 NoiseHandshakeState *handshake; 9 // Used to encrypt packets of this peer(ChaCha20-Poly1305) 10 NoiseCipherState *send_cipher; 11 // Used to decrypt received packets sent from the other peer(ChaCha20-Poly1305) 12 NoiseCipherState *recv_cipher; 13 [...] 14 } Crypto_Connection; Listing 4.5: Adapted Crypto_Connection struct (ChaCha20-based transport phase)

The base nonce and the session public key from the remote peer are not needed anymore in the New_Connection struct, instead a temporary NoiseHandshakeState is necessary (see listing 4.6).

1 typedef struct New_Connection { 2 IP_Port source; 3 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The static public key of the peer. */ 4 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The dht public key of the peer. */ 5 // Base nonce and peer session public key are handled by Noise 6 // uint8_t recv_nonce[CRYPTO_NONCE_SIZE];/ * Base nonce of received packets. */

54 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

7 // uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The ephemeral public key of the peer. */ 8 uint8_t *cookie; 9 uint8_t cookie_length; 10 // Temporary handshake object in New_connection 11 NoiseHandshakeState *handshake_temp; 12 } New_Connection; Listing 4.6: Adapted New_Connection struct (ChaCha20-based transport phase)

For the Noise-based handshake the packets sent during the AKE have different lengths, 409 bytes (initiator) and 361 bytes (responder). Therefore two defines are needed in net_crypto.c (see listing 4.7).

1 #define HANDSHAKE_PACKET_LENGTH_RESPONDER (1 + COOKIE_LENGTH + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE) 2 #define HANDSHAKE_PACKET_LENGTH_INITIATOR (1 + COOKIE_LENGTH + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE) Listing 4.7: Different packet lengths for initiator and responder in net_crypto.c

The initiator creates a NoiseHandshakeState in new_crypto_connection() by setting the Noise protocol and Noise role accordingly (i.e. initiator; see listing 4.8). The responder creates it in handle_new_connection_handshake() and sets the role to NOISE_ROLE_RESPONDER.

1 int err = noise_handshakestate_new_by_name(&conn->handshake, CRYPTO_NOISE_PROTOCOL_NAME, NOISE_ROLE_INITIATOR); 2 [Error handling] Listing 4.8: Creation of a NoiseHandshakeState as initiator

In a initialize_handshake() function the prologue, the static private key of the local peer and the static public key of the remote peer are set (see listing 4.9). The static public key of the remote peer is only set by the initiator of the handshake.

1 static int initialize_handshake(NoiseHandshakeState *handshake, const uint8_t * self_secret_key, const uint8_t *peer_public_key) { 2 // DHState objects are used to store the key pairs for the local party or the public keys for remote parties. 3 NoiseDHState *dh; 4 size_t key_len = 0; 5 int err; 6 // Set prologue to CRYPTO_NOISE_PROTOCOL_NAME 7 err = noise_handshakestate_set_prologue(handshake, CRYPTO_NOISE_PROTOCOL_NAME, sizeof( CRYPTO_NOISE_PROTOCOL_NAME)); 8 [Error handling] 9 if (self_secret_key) { 10 // Load the local key pair of this peer 11 dh = noise_handshakestate_get_local_keypair_dh(handshake); 12 key_len = noise_dhstate_get_private_key_length(dh); 13 // Set the local peers static private key from Net_crypto object(c-> self_secret_key) 14 err = noise_dhstate_set_keypair_private(dh, self_secret_key, key_len); 15 [Error handling] 16 } [Error handling] 17 //IK pattern and initiator role => static public key of remote peer is also necessary 18 int role = noise_handshakestate_get_role(handshake); 19 if (role == NOISE_ROLE_INITIATOR) { 20 if (peer_public_key) {

55 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

21 dh = noise_handshakestate_get_remote_public_key_dh(handshake); 22 key_len = noise_dhstate_get_public_key_length(dh); 23 // Set the remote peers static public key(conn->public_key) 24 err = noise_dhstate_set_public_key(dh, peer_public_key, key_len); 25 [Error handling] 26 } [Error handling] 27 } 28 /* Ready to go */ 29 return 0; 30 } Listing 4.9: initialize_handshake() function to set prologue, static secret key of the local peer and static public key of the remote peer

The initialize_handshake() function is called in new_crypto_connection() by the initiator (see listing 4.10) and in handle_new_connection_handshake() by the responder.

1 if (initialize_handshake(conn->handshake, c->self_secret_key, conn->public_key) == -1) { 2 noise_handshakestate_free(conn->handshake); 3 return -1; 4 } Listing 4.10: Initialization of the NoiseHandshakeState object

Now it’s possible to actually start the Noise handshake. The initiator calls noise_h andshakestate_start() in handle_packet_connection() after receiving a cookie response packet (see listing 4.11). The responder calls noise_handshakestate_start() in handle_new_connection_handshake() after receiving a handshake packet from the initiator (see listing 4.12).

1 int role = noise_handshakestate_get_role(conn->handshake); 2 if (role == NOISE_ROLE_INITIATOR) { 3 int err = noise_handshakestate_start(conn->handshake); 4 [Error handling] 5 int action = noise_handshakestate_get_action(conn->handshake); 6 if (action == NOISE_ACTION_WRITE_MESSAGE) { 7 // If cookie response was ok, create and senda handshake packet to responder 8 if (create_send_handshake(c, crypt_connection_id, cookie, conn->dht_public_key) != 0) { 9 return -1; 10 } 11 } 12 } Listing 4.11: Initiator starts the handshake in handle_packet_connection()

1 int role = noise_handshakestate_get_role(n_c.handshake_temp); 2 if (role == NOISE_ROLE_RESPONDER) { 3 int err = noise_handshakestate_start(n_c.handshake_temp); 4 [Error handling] 5 int action = noise_handshakestate_get_action(n_c.handshake_temp); 6 if (action == NOISE_ACTION_READ_MESSAGE) { 7 // Handle the crypto handshake packet from peerA/initiator(incl. other cookie fromA) 8 if (handle_crypto_handshake(c, n_c.public_key, n_c.dht_public_key, 9 n_c.cookie, data, length, nullptr, n_c.handshake_temp) != 0) { 10 free(n_c.cookie); 11 return -1; 12 } 13 } 14 } [Error handling] Listing 4.12: Responder starts the handshake in handle_new_connection_handshake()

56 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

Listing 4.13 shows create_crypto_handshake() which is called by create_send_ handshake(). This function is used by both peers, from the initiator via handle_pac ket_connection() and from the responder via accept_crypto_connection()), to create the proper handshake packet by performing the computations of the corresponding Noise message pattern depending on the Noise role.

1 static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const uint8_t * cookie, const uint8_t *peer_real_pk, const uint8_t *peer_dht_pubkey, NoiseHandshakeState *handshake) { 2 int role = noise_handshakestate_get_role(handshake); 3 if (role == NOISE_ROLE_RESPONDER) { 4 // Noise message+ application chosen payload 5 NoiseBuffer noise_message; 6 // Ephemeral public key of the responder+ encrypted payload+ MAC of encrypted payload 7 uint8_t noise_message_buf[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE]; 8 // Application chosen payload of Noise message 9 NoiseBuffer noise_payload; 10 // Payload contains SHA512 hash of cookie(initiator) and other cookie(responder) 11 uint8_t noise_payload_buf[CRYPTO_SHA512_SIZE + COOKIE_LENGTH ]; 12 // Add SHA512 hash of cookie to payload 13 crypto_sha512(noise_payload_buf, cookie, COOKIE_LENGTH); 14 uint8_t othercookie_plain[COOKIE_DATA_LENGTH ]; 15 memcpy(othercookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE); 16 memcpy(othercookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); 17 // Creation of the other cookie from PeerB/responder 18 if (create_cookie(c->log, c->mono_time, noise_payload_buf + CRYPTO_SHA512_SIZE, othercookie_plain, c->secret_symmetric_key) != 0) { return -1; } 19 noise_buffer_set_input(noise_payload, noise_payload_buf,sizeof(noise_payload_buf)); 20 noise_buffer_set_output(noise_message,noise_message_buf,sizeof(noise_message_buf)); 21 // Computes Noise messageB pattern"e, ee, se" 22 int err = noise_handshakestate_write_message(handshake, &noise_message, & noise_payload); 23 [Error handling] 24 // Write packet kind, cookie and noise message incl. payload to packet 25 packet[0] = NET_PACKET_CRYPTO_HS; 26 memcpy(packet + 1, cookie, COOKIE_LENGTH); 27 memcpy(packet + 1 + COOKIE_LENGTH, noise_message_buf,sizeof(noise_message_buf)); 28 return HANDSHAKE_PACKET_LENGTH_RESPONDER; 29 } else if (role == NOISE_ROLE_INITIATOR) { 30 NoiseBuffer noise_message; 31 // Ephemeral pubkey initiator+ static pubkey initiator+ MAC static pubkey+ encrypted payload+ MAC of encrypted payload 32 uint8_t noise_message_buf[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE]; 33 NoiseBuffer noise_payload; 34 // Payload contains SHA512 hash of cookie(responder) and other cookie(initiator) 35 uint8_t noise_payload_buf[CRYPTO_SHA512_SIZE + COOKIE_LENGTH ]; 36 crypto_sha512(noise_payload_buf, cookie, COOKIE_LENGTH); 37 uint8_t othercookie_plain[COOKIE_DATA_LENGTH ]; 38 memcpy(othercookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE); 39 memcpy(othercookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); 40 // Creation of other cookie from PeerA/initiator 41 if (create_cookie(c->log, c->mono_time, noise_payload_buf + CRYPTO_SHA512_SIZE, othercookie_plain, c->secret_symmetric_key) != 0) { 42 return -1; 43 } 44 noise_buffer_set_input(noise_payload, noise_payload_buf,sizeof(noise_payload_buf)); 45 noise_buffer_set_output(noise_message,noise_message_buf,sizeof(noise_message_buf)); 46 // Computes Noise messageA pattern"e, es,s, ss" 47 int err = noise_handshakestate_write_message(handshake, &noise_message, & noise_payload); 48 [Error handling] 49 // Write packet kind, cookie and noise message incl. payload to packet

57 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

50 packet[0] = NET_PACKET_CRYPTO_HS; 51 memcpy(packet + 1, cookie, COOKIE_LENGTH); 52 memcpy(packet + 1 + COOKIE_LENGTH, noise_message_buf, sizeof(noise_message_buf)); 53 return HANDSHAKE_PACKET_LENGTH_INITIATOR; 54 } [Error handling] 55 } Listing 4.13: create_crypto_handshake() is called by both peers to create a handshake packet

Listing 4.14 shows handle_crypto_handshake(). This function is called by both peers, from the initiator via handle_packet_connection() and from the responder via handle_new_connection_handshake()), to handle the received handshake packet by performing the computations of the corresponding Noise message pattern depending on the Noise role.

1 static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *peer_real_pk, uint8_t * dht_public_key, uint8_t *cookie, const uint8_t *packet, uint16_t length, const uint8_t *expected_real_pk, NoiseHandshakeState *handshake) { 2 // Get handhake role => different handshake packet lengths 3 int role = noise_handshakestate_get_role(handshake); 4 if (role == NOISE_ROLE_RESPONDER) { 5 if (length != HANDSHAKE_PACKET_LENGTH_INITIATOR) { 6 return -1; 7 } 8 } else if (role == NOISE_ROLE_INITIATOR) { 9 if (length != HANDSHAKE_PACKET_LENGTH_RESPONDER) { 10 return -1; 11 } 12 } [Error handling] 13 uint8_t cookie_plain[COOKIE_DATA_LENGTH ]; 14 // The peer opens their cookie to verify it’s really theirs 15 if (open_cookie(c->log, c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key ) != 0) { 16 return -1; 17 } 18 if (expected_real_pk) { 19 if (public_key_cmp(cookie_plain, expected_real_pk) != 0) { 20 return -1; 21 } 22 } 23 uint8_t cookie_hash[CRYPTO_SHA512_SIZE]; 24 // Calculating the hash of the cookie outside of the Noise payload 25 crypto_sha512(cookie_hash, packet + 1, COOKIE_LENGTH); 26 // Responder receives handshake packet from initiator= longer packet 27 if (role == NOISE_ROLE_RESPONDER) { 28 NoiseBuffer noise_message; 29 // Ephemeral pubkey+ encrypted initiator static pubkey+ MAC static pubkey+ encrypted payload+ MAC of encrypted payload 30 uint8_t noise_message_buf[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE]; 31 // Copy the data from packet to the noise_message_buf 32 memcpy(noise_message_buf, packet + 1 + COOKIE_LENGTH, HANDSHAKE_PACKET_LENGTH_INITIATOR - 1 - COOKIE_LENGTH); 33 NoiseBuffer noise_payload; 34 // Payload contains SHA512 hash of cookie(responder) and other cookie(initiator) 35 uint8_t noise_payload_buf[CRYPTO_SHA512_SIZE + COOKIE_LENGTH ]; 36 noise_buffer_set_input(noise_payload, noise_payload_buf,sizeof(noise_payload_buf)); 37 noise_buffer_set_input(noise_message, noise_message_buf,sizeof(noise_message_buf)); 38 // Computes Noise messageA pattern"e, es,s, ss" on responder side 39 int err = noise_handshakestate_read_message(handshake, &noise_message, & noise_payload); 40 [Error handling] 41 // Copy other cookie from initiator 42 memcpy(cookie, noise_payload.data + CRYPTO_SHA512_SIZE, COOKIE_LENGTH); 43 if (crypto_memcmp(cookie_hash, noise_payload.data, CRYPTO_SHA512_SIZE) != 0) {

58 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

44 return -1; 45 } 46 // Memcpy peer_real_pk+ dht_public_key from cookie_plain 47 memcpy(peer_real_pk, cookie_plain, CRYPTO_PUBLIC_KEY_SIZE); 48 memcpy(dht_public_key, cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE); 49 } 50 // Initiator receives handshake packet from responder= shorter packet 51 else if (role == NOISE_ROLE_INITIATOR) { 52 NoiseBuffer noise_message; 53 // Ephemeral pubkey responder+ encrypted payload+ MAC of encrypted payload 54 uint8_t noise_message_buf[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE]; 55 // Copy the data from packet to the noise_message_buf 56 memcpy(noise_message_buf, packet + 1 + COOKIE_LENGTH, HANDSHAKE_PACKET_LENGTH_RESPONDER - 1 - COOKIE_LENGTH); 57 NoiseBuffer noise_payload; 58 // Payload contains SHA512 hash of cookie and other cookie 59 uint8_t noise_payload_buf[CRYPTO_SHA512_SIZE + COOKIE_LENGTH ]; 60 noise_buffer_set_input(noise_payload, noise_payload_buf,sizeof(noise_payload_buf)); 61 noise_buffer_set_input(noise_message, noise_message_buf,sizeof(noise_message_buf)); 62 // Computes Noise messageB pattern"e, ee, se" on initiator side 63 int err = noise_handshakestate_read_message(handshake, &noise_message, & noise_payload); 64 [Error handling] 65 // Copy other cookie from responder 66 memcpy(cookie, noise_payload.data + CRYPTO_SHA512_SIZE, COOKIE_LENGTH); 67 if (crypto_memcmp(cookie_hash, noise_payload.data, CRYPTO_SHA512_SIZE) != 0) { 68 return -1; 69 } 70 // Memcpy peer_real_pk+ dht_public_key from cookie_plain 71 memcpy(peer_real_pk, cookie_plain, CRYPTO_PUBLIC_KEY_SIZE); 72 memcpy(dht_public_key, cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE); 73 } [Error handling] 74 return 0; 75 } Listing 4.14: handle_crypto_handshake() is called by both peers when a handshake packet is received

After the initiator successfully received the handshake packet from the responder the two NoiseCipherState objects (for sending and receiving of encrypted packets) are split out of the NoiseHandshakeState object in handle_packet_connection(). The responder also splits out the two NoiseCipherState objects, but in this case after sending the handshake packet to the initiator in accept_crypto_connection(). After the two NoiseCipherState objects are successfully retrieved, the NoiseHandshakeState object is not required anymore and therefore the memory is freed (see listing 4.15).

1 /* If the action is not"split", then the handshake has failed */ 2 if (noise_handshakestate_get_action(conn->handshake) != NOISE_ACTION_SPLIT) { 3 [Error handling] 4 return -1; 5 } 6 else{/ * Split out the two CipherState objects for send and receive */ 7 int err = noise_handshakestate_split(conn->handshake, &conn->send_cipher, &conn-> recv_cipher); 8 [Error handling] 9 noise_handshakestate_free(conn->handshake);/ * We no longer need the HandshakeState */ 10 conn->handshake = 0; 11 } Listing 4.15: Splitting the NoiseHandshakeState in two NoiseCipherState objects

59 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

Following a successful handshake, the send_data_packet() (see listing 4.16) and handle_data_packet() (see listing 4.17) functions are used to send respectively re- ceive encrypted messages. Encryption and decryption is performed by using the functions noise_cipherstate_encrypt() respectively noise_cipherstate_decrypt() from Noise-C. These functions need the proper NoiseCipherState as parameter, which con- tains the key and nonce used for symmetric encryption/decryption with ChaCha20-Poly1305. The resulting encrypted packets have the same structure as shown in figure 2.12, but the last two bytes of the base nonce are not included.

1 static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) { 2 const uint16_t max_length = MAX_CRYPTO_PACKET_SIZE - (1 + CRYPTO_MAC_SIZE); 3 if (length == 0 || length > max_length) { 4 return -1; 5 } 6 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 7 if (conn == nullptr) { 8 return -1; 9 } 10 pthread_mutex_lock(conn->mutex); 11 VLA(uint8_t, packet, 1 + length + CRYPTO_MAC_SIZE); 12 packet[0] = NET_PACKET_CRYPTO_DATA; 13 /* Encrypt the message and send it */ 14 NoiseBuffer noise_message; 15 // We cannot just use *data directly => we need memory for MAC 16 uint8_t noise_message_buf[length + CRYPTO_MAC_SIZE]; 17 memcpy(noise_message_buf, data, length); 18 noise_buffer_set_inout(noise_message, noise_message_buf, length, sizeof( noise_message_buf)); 19 // Encryption of packet payload 20 int err = noise_cipherstate_encrypt(conn->send_cipher, &noise_message); 21 // The threshold for the counter-based nonce in Noise is 2^64-1 22 if (err != NOISE_ERROR_NONE) { 23 if (err == NOISE_ERROR_INVALID_NONCE) { 24 [Error handling] 25 } 26 } 27 // Copy ciphertext to packet 28 memcpy(packet + 1, noise_message_buf, sizeof(noise_message_buf)); 29 pthread_mutex_unlock(conn->mutex); 30 return send_packet_to(c, crypt_connection_id, packet, SIZEOF_VLA(packet)); 31 } Listing 4.16: send_data_packet(): encryption based on ChaCha20-Poly1305

1 static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint8_t *data, const uint8_t *packet, uint16_t length) { 2 const uint16_t crypto_packet_overhead = 1 + CRYPTO_MAC_SIZE; 3 // Length is1+ encrypted payload+ MAC 4 if (length <= crypto_packet_overhead || length > MAX_CRYPTO_PACKET_SIZE) { 5 return -1; 6 } 7 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 8 if (conn == nullptr) { 9 return -1; 10 } 11 NoiseBuffer noise_message; 12 // Can’t just use *data directly => need memory for MAC 13 uint8_t noise_message_buf[length - 1]; 14 // Copy encrypted payload and MAC 15 memcpy(noise_message_buf, packet + 1, length - 1); 16 /* Decrypt the incoming message */ 17 noise_buffer_set_input(noise_message, noise_message_buf, sizeof(noise_message_buf)); 18 int err = noise_cipherstate_decrypt(conn->recv_cipher, &noise_message); 19 if (err != NOISE_ERROR_NONE) {

60 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

20 // Verify if Nonce overflowed 21 if (err == NOISE_ERROR_INVALID_NONCE) { 22 [Error handling] 23 } 24 } 25 // Memcpy plaintext to data 26 memcpy(data, noise_message.data, noise_message.size); 27 return noise_message.size; 28 } Listing 4.17: handle_data_packet(): decryption based on ChaCha20-Poly1305

4.3.1. Testing Tox’ Noise-based Handshake Behavior with minitox

The minitox Tox client was used to test the handshake behavior. This was done on a Debian 10/Buster VirtualBox3 virtual machine, which has libsodium and Noise-C installed. Toxcore, including the Noise-based handshake and some debug outputs, is built using libsodium and Noise-C (see appendix A.3 to A.5.1). Then minitox is built by using the adapted c-toxcore version (see appendix A.5.2). Multiple instances of minitox were started and each instance added the others as friends. After accepting the friendship, each pair of two instances performed a successful Noise-based handshake and was able to exchange encrypted messages. If the minitox clients, with al- ready existing friends, were restarted, they again performed successful handshakes with their friends. Note that this test was done in a non-realistic scenario because all clients are run- ning on the same machine and therefore no packets are lost (which is likely to happen when communicating via UDP).

4.3.2. Testing UDP Packet Loss with flakynet (ChaCha20-Poly1305)

To test the Noise-based handshake in a realistic scenario, flakynet was used to simulate UDP packet loss. Flakynet is a simple LD_PRELOAD wrapper dropping UDP packets sent via sendto(). That means the shared object of flakynet is loaded before running minitox and therefore dropping UDP packets sent by minitox. For more information on how to build flakynet and running it together with minitox see appendix A.5.3. In the flakynet.c source file it is possible to configure the percentage of packets that should be dropped (e.g. 20% of all packets). Running multiple minitox instances with flakynet quickly led to the realization that this implementation cannot handle UDP packet loss. If only one encrypted packet is lost this leads to a noise_cipherstate_decrypt: MAC failure error at the receiving peer. This happens because the nonce n is handled by Noise-C in the NoiseCipherState object. If a packet x is lost, but the packet x + 1 is received, the peer receiving the packet will use n to decrypt the packet, but packet x + 1 is encrypted with n + 1. Therefore the packet is not correctly decrypted, which leads to a wrong MAC value. The Noise specification states in section "11.4. Out-of-order transport messages" that "an application protocol can send the n value used for encrypting each transport message alongside that message. On receiving such a message the recipient would call the SetNonce() function on the receiving CipherState using the received n value" [Per18]. Therefore the nonce for each encrypted packet would need to be sent together with that packet. This introduces more complexity because recipients must track the received n value for which decryption

3https://www.virtualbox.org/

61 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

was successful and reject any messages which repeat such a value to prevent replay attacks. The SetNonce() function implemented in Noise-C is not compatible with this section of the Noise specification. The noise_cipherstate_set_nonce() function provided by Noise- C takes a NoiseCipherState object and the 8-byte nonce value that are set as parameters. The issue is, that this nonce value must be greater than or equal to the current nonce value in the state. Obviously this is not always the case if UDP packets arrive out-of-order4. It would be possible to implement the noise_cipherstate_set_nonce() function in such a way, that it is possible to also set nonce values lower than the current nonce value in the state. Then it would still be necessary to implement the packet loss functionality in c- toxcore accordingly. Since UDP is also used with the non-Noise Tox handshake, such a UDP packet loss mechanism is already implemented in c-toxcore for XSalsa20-Poly1305 encryption with 24-byte nonces. So instead of reimplementing such a mechanism for ChaCha20-Poly1305 encryption with 8-byte nonces, it was tried to implement the Noise-based handshake by using XSalsa20-Poly1305 during the transport phase instead of ChaCha20-Poly1305 (see section 4.4).

4.4. Final Implementation with Chacha20-Poly1305 during the AKE and XSalsa20-Poly1305 during the Transport Phase

This implementation approach is based on the last commit of branch tb_noise_handshake_IK. Therefore only the differences to the implementation description of section 4.3 are outlined. send After a successful Noise handshake the two NoiseCipherState objects (containing TA recv respectively TA and n) are split out of the NoiseHandshakeState. These NoiseCip herState objects are intended to be used with encryption/decryption functions provided by Noise-C. It is currently not in the scope of the Noise framework specification and its im- send recv plementation in Noise-C to retrieve the keys (TA , TA ) from a NoiseCipherState object. Since the Noise-C library is open source, it’s possible to add a function to re- trieve the keys after a successful handshake. Hence two functions were added to Noise-C, namely noise_handshakestate_split_without_noisecipherstate() (see listing 4.18) and noise_symmetricstate_split_without_noisecipherstate() (see list- ing 4.19), to be able to use the keys with the existing XSalsa20-Poly1305 encryption/decryp- tion in c-toxcore. This means that this implementation is not completely compliant with the Noise framework specification. From a security point of view this doesn’t make a difference. The new function noise_handshakestate_split_without_noisecipherstate() is based on the function noise_handshakestate_split(). Function noise_symmetr icstate_split_without_noisecipherstate() is based on noise_symmetricsta te_split() from Noise-C. The functions were added to the source files handshakestate.c re- spectively symmetricstate.c and the function prototypes to the header files handshakestate.h respectively symmetricstate.h. Both new functions are provided with arrays to save the sending and receiving keys, instead of NoiseCipherState structs.

1 int noise_handshakestate_split_without_noisecipherstate 2 (NoiseHandshakeState *state, uint8_t *send, uint8_t *receive) { 3 int swap; 4 int err; 5 /* Validate the parameters */

4GitHub user "aep" already reported this issue on 29.04.2019: https://github.com/rweather/noise- c/issues/39

62 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

6 if (!state) 7 return NOISE_ERROR_INVALID_PARAM; 8 if (!send && !receive) 9 return NOISE_ERROR_INVALID_PARAM; 10 if (state->action != NOISE_ACTION_SPLIT) 11 return NOISE_ERROR_INVALID_STATE; 12 if (!state->symmetric->cipher) 13 return NOISE_ERROR_INVALID_STATE; 14 /* Do we need to swap the CipherState objects for the role? */ 15 swap = (state->role == NOISE_ROLE_RESPONDER); 16 /* Split the CipherState objects out of the SymmetricState */ 17 if (swap) 18 err = noise_symmetricstate_split_without_noisecipherstate(state->symmetric,receive, send); 19 else 20 err = noise_symmetricstate_split_without_noisecipherstate(state->symmetric, send, receive); 21 if (err == NOISE_ERROR_NONE) 22 state->action = NOISE_ACTION_COMPLETE; 23 return err; 24 } Listing 4.18: Function added to handshakestate.c of Noise-C

1 int noise_symmetricstate_split_without_noisecipherstate 2 (NoiseSymmetricState *state, uint8_t *k1, uint8_t *k2) { 3 uint8_t temp_k1[NOISE_MAX_HASHLEN]; 4 uint8_t temp_k2[NOISE_MAX_HASHLEN]; 5 size_t hash_len; 6 size_t key_len; 7 /* Validate the parameters */ 8 if (!state) 9 return NOISE_ERROR_INVALID_PARAM; 10 if (!k1 && !k2) 11 return NOISE_ERROR_INVALID_PARAM; 12 /* If the state has already been split, then we cannot split again */ 13 if (!state->cipher) 14 return NOISE_ERROR_INVALID_STATE; 15 /* Generate the two encryption keys with HKDF */ 16 hash_len = noise_hashstate_get_hash_length(state->hash); 17 key_len = noise_cipherstate_get_key_length(state->cipher); 18 noise_hashstate_hkdf(state->hash, state->ck, hash_len, state->ck, 0, 19 temp_k1, key_len, temp_k2, key_len); 20 /* Copy both keys to provided arrays */ 21 memcpy(k1, temp_k1, key_len); 22 memcpy(k2, temp_k2, key_len); 23 state->cipher = 0; 24 noise_clean(temp_k1, sizeof(temp_k1)); 25 noise_clean(temp_k2, sizeof(temp_k2)); 26 return NOISE_ERROR_NONE; 27 } Listing 4.19: Function added to symmetricstate.c of Noise-C

The Crypto_Connection struct needs to be adapted due to the use of arrays (instead of NoiseCipherState objects) and XSalsa20 instead of ChaCha20. For XSalsa20 encryption the base nonces of both peers (i.e. initiator and responder) are needed which isn’t necessary for the ChaCha20-based implementation (see listing 4.20).

1 typedef struct Crypto_Connection { 2 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The real public key of the peer. */ 3 // Base nonces of initiator and responder 4 uint8_t recv_nonce[CRYPTO_NONCE_SIZE];/ * Nonce of received packets. */ 5 uint8_t sent_nonce[CRYPTO_NONCE_SIZE];/ * Nonce of sent packets. */ 6 // Shared_key is still used in the cookie phase(DHT-based shared_key) 7 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];/ * The precomputed shared key from encrypt_precompute. */

63 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

8 Crypto_Conn_State status;/ * See Crypto_Conn_State documentation */ 9 uint64_t cookie_request_number;/ * Number used in the cookie request packets for this connection(echoID!) */ 10 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The dht public key of the peer */ 11 // HandshakeState is also needed in this case 12 NoiseHandshakeState *handshake; 13 // Arrays instead of NoiseCipherState 14 // Key used to encrypt packets of the local peer(XSalsa20-Poly1305) 15 uint8_t send_key[CRYPTO_PUBLIC_KEY_SIZE]; 16 // Key used to decrypt packets of the remote peer(XSalsa20-Poly1305) 17 uint8_t recv_key[CRYPTO_PUBLIC_KEY_SIZE]; 18 [...] 19 } Crypto_Connection; Listing 4.20: Adapted Crypto_Connection struct (XSalsa20-based transport phase)

The base nonce from the remote peer is also needed again in the New_Connection struct. Apart from that it’s identical with the ChaCha20-based implementation (see listing 4.21, cf. listing 4.6).

1 typedef struct New_Connection { 2 IP_Port source; 3 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The static public key of the peer. */ 4 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];/ * The dht public key of the peer. */ 5 // Base nonce NOT handled by Noise 6 uint8_t recv_nonce[CRYPTO_NONCE_SIZE];/ * Base nonce of received packets. */ 7 [...] 8 } New_Connection; Listing 4.21: Adapted New_Connection struct (XSalsa20-based transport phase)

For the Noise-based handshake with XSalsa20 encryption/decryption the packets, that are sent during the AKE, also have different lengths and additionally include a base nonce. The packet sizes are 433 bytes (initiator) and 385 bytes (responder). Two defines are needed in net_crypto.c again (see listing 4.22).

1 #define HANDSHAKE_PACKET_LENGTH_RESPONDER (1 + COOKIE_LENGTH + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE) 2 #define HANDSHAKE_PACKET_LENGTH_INITIATOR (1 + COOKIE_LENGTH + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE) Listing 4.22: Different packet lengths for initiator and responder in net_crypto.c (including a base nonce)

The initialize_handshake() function (as shown in listing 4.9) stays the same, as well as the calls to noise_handshakestate_start() (cf. listings 4.11 and 4.12). The creation of handshake packets in create_crypto_handshake() and the handling of received handshake packets in handle_crypto_handshake() is adapted because it’s necessary to add the local base nonce to the handshake packet (see listing 4.23) and to retrieve the base nonce of the remote peer from the handshake packet (see listing 4.24).

1 static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const uint8_t * cookie, const uint8_t *nonce, const uint8_t *peer_real_pk, const uint8_t * peer_dht_pubkey, NoiseHandshakeState *handshake) { 2 int role = noise_handshakestate_get_role(handshake); 3 if (role == NOISE_ROLE_RESPONDER) { 4 // Noise message+ Application chosen payload 5 NoiseBuffer noise_message;

64 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

6 // Ephemeral public key of the responder+ encrypted payload(incl. base nonce of responder)+ MAC of encrypted payload 7 uint8_t noise_message_buf[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE]; 8 NoiseBuffer noise_payload; 9 // Payload contains base nonce, SHA512 hash of cookie(initiator) and other cookie (responder) 10 uint8_t noise_payload_buf[CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH ]; 11 // Add base nonce to payload 12 memcpy(noise_payload_buf, nonce, CRYPTO_NONCE_SIZE); 13 // Add SHA512 hash of cookie to payload 14 crypto_sha512(noise_payload_buf + CRYPTO_NONCE_SIZE, cookie, COOKIE_LENGTH); 15 uint8_t othercookie_plain[COOKIE_DATA_LENGTH ]; 16 memcpy(othercookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE); 17 memcpy(othercookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); 18 if (create_cookie(c->log, c->mono_time, noise_payload_buf + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE, othercookie_plain, c->secret_symmetric_key) != 0) { 19 return -1; 20 } 21 [Same code as in ChaCha20-based implementation] 22 return HANDSHAKE_PACKET_LENGTH_RESPONDER; 23 } else if (role == NOISE_ROLE_INITIATOR) { 24 NoiseBuffer noise_message; 25 // Ephemeral pubkey initiator+ static pubkey initiator+ MAC static pubkey+ encrypted payload(incl. base nonce initiator)+ MAC of encrypted payload 26 uint8_t noise_message_buf[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE]; 27 NoiseBuffer noise_payload; 28 // Payload contains base nonce, SHA512 hash of cookie(responder) and other cookie (initiator) 29 uint8_t noise_payload_buf[CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH ]; 30 // Add base nonce to payload 31 memcpy(noise_payload_buf, nonce, CRYPTO_NONCE_SIZE); 32 crypto_sha512(noise_payload_buf + CRYPTO_NONCE_SIZE, cookie, COOKIE_LENGTH); 33 uint8_t othercookie_plain[COOKIE_DATA_LENGTH ]; 34 memcpy(othercookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE); 35 memcpy(othercookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); 36 if (create_cookie(c->log, c->mono_time, noise_payload_buf + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE, othercookie_plain, c->secret_symmetric_key) != 0) { 37 return -1; 38 } 39 [Same code as in ChaCha20-based implementation] 40 return HANDSHAKE_PACKET_LENGTH_INITIATOR; 41 } Listing 4.23: create_crypto_handshake() with base nonce

1 static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t * peer_real_pk, uint8_t *dht_public_key, uint8_t *cookie, const uint8_t *packet, uint16_t length, const uint8_t *expected_real_pk, NoiseHandshakeState *handshake) { 2 int role = noise_handshakestate_get_role(handshake); 3 [Same code as in ChaCha20-based implementation] 4 // Responder receives handshake packet from initiator= longer packet 5 if (role == NOISE_ROLE_RESPONDER) { 6 NoiseBuffer noise_message; 7 // Ephemeral pubkey+ encrypted initiator static pubkey+ MAC static pubkey+ encrypted payload(incl. base nonce)+ MAC of encrypted payload 8 uint8_t noise_message_buf[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE]; 9 // Copy the data from packet to the noise_message_buf 10 memcpy(noise_message_buf, packet + 1 + COOKIE_LENGTH, HANDSHAKE_PACKET_LENGTH_INITIATOR - 1 - COOKIE_LENGTH); 11 NoiseBuffer noise_payload; 12 // Payload contains base nonce, SHA512 hash of cookie(responder) and other cookie (initiator) 13 uint8_t noise_payload_buf[CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH ];

65 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

14 noise_buffer_set_input(noise_payload, noise_payload_buf,sizeof(noise_payload_buf)); 15 noise_buffer_set_input(noise_message, noise_message_buf,sizeof(noise_message_buf)); 16 // Computes Noise messageA pattern"e, es,s, ss" on responder side 17 int err = noise_handshakestate_read_message(handshake, &noise_message, & noise_payload); 18 [Error handling] 19 // Copy base nonce from the decrypted payload 20 memcpy(nonce, noise_payload.data, CRYPTO_NONCE_SIZE); 21 // Copy other cookie 22 memcpy(cookie, noise_payload.data + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE, COOKIE_LENGTH); 23 if (crypto_memcmp(cookie_hash, noise_payload.data + CRYPTO_NONCE_SIZE, CRYPTO_SHA512_SIZE) != 0) { 24 return -1; 25 } 26 // Memcpy peer_real_pk+ dht_public_key from cookie_plain 27 memcpy(peer_real_pk, cookie_plain, CRYPTO_PUBLIC_KEY_SIZE); 28 memcpy(dht_public_key, cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE); 29 } 30 // Initiator receives handshake packet from responder= shorter packet 31 else if (role == NOISE_ROLE_INITIATOR) { 32 NoiseBuffer noise_message; 33 // Ephemeral pubkey responder+ encrypted payload(incl. base nonce)+ MAC of encrypted payload 34 uint8_t noise_message_buf[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE]; 35 // Copy the data from packet to the noise_message_buf 36 memcpy(noise_message_buf, packet + 1 + COOKIE_LENGTH, HANDSHAKE_PACKET_LENGTH_RESPONDER - 1 - COOKIE_LENGTH); 37 NoiseBuffer noise_payload; 38 // Payload contains base nonce, SHA512 hash of cookie and other cookie 39 uint8_t noise_payload_buf[CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH ]; 40 noise_buffer_set_input(noise_payload, noise_payload_buf,sizeof(noise_payload_buf)); 41 noise_buffer_set_input(noise_message, noise_message_buf,sizeof(noise_message_buf)); 42 // Computes Noise messageB pattern"e, ee, se" on initiator side 43 int err = noise_handshakestate_read_message(handshake, &noise_message, & noise_payload); 44 [Error handling] 45 // Copy base nonce from the decrypted payload 46 memcpy(nonce, noise_payload.data, CRYPTO_NONCE_SIZE); 47 memcpy(cookie, noise_payload.data + CRYPTO_NONCE_SIZE + CRYPTO_SHA512_SIZE, COOKIE_LENGTH); 48 if (crypto_memcmp(cookie_hash, noise_payload.data + CRYPTO_NONCE_SIZE, CRYPTO_SHA512_SIZE) != 0) { 49 return -1; 50 } 51 memcpy(peer_real_pk, cookie_plain, CRYPTO_PUBLIC_KEY_SIZE); 52 memcpy(dht_public_key, cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE); 53 } else{ 54 return -1; 55 } 56 return 0; 57 } Listing 4.24: handle_crypto_handshake() with base nonce

After the initiator successfully received the handshake packet from the responder, the two arrays, for saving the sending and receiving keys to encrypt/decrypt packets, are split out of the NoiseHandshakeState object in handle_packet_connection(). This is done by calling noise_handshakestate_split_without_noisecipherstate() instead of noise_handshakestate_split() (see listing 4.25). The responder does the same but after sending the handshake packet to the initiator in accept_crypto_connection(). After the the two keys for symmetric encryption/decryption were successfully retrieved, the NoiseHandshakeState object is not required anymore and therefore the memory is freed.

66 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

1 // Initiator is now finished with the handshake 2 /* If the action is not"split", the handshake has failed */ 3 if (noise_handshakestate_get_action(conn->handshake) != NOISE_ACTION_SPLIT) { 4 [Error handling] 5 return -1; 6 } 7 /* Split out the two CipherState objects for send and receive */ 8 else{ 9 int err = noise_handshakestate_split_without_noisecipherstate(conn->handshake, conn-> send_key, conn->recv_key); 10 if (err != NOISE_ERROR_NONE) { 11 [Error handling] 12 return -1; 13 } 14 /* We no longer need the HandshakeState */ 15 noise_handshakestate_free(conn->handshake); 16 conn->handshake = 0; 17 } Listing 4.25: NoiseHandshakeState is split in two arrays instead of two NoiseCipherState objects

After a successful handshake, the send_data_packet() (see listing 4.26) and handle_ data_packet() (see listing 4.27) functions are used to send respectively receive encrypted messages. XSalsa20-Poly1305 encryption and decryption is performed using the functions encrypt_data_symmetric() respectively decrypt_data_symmetric(). These func- tions are provided with the necessary key (i.e. either the sending or receiving key) and the base nonce corresponding to that key. This is done instead of using the two NoiseCipherSt ate objects with ChaCha20-Poly1305 encryption/decryption functions provided by Noise-C. The resulting encrypted packets have the same structure as shown in figure 2.12.

1 static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) { 2 const uint16_t max_length = MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE);// Sizeof(uint16_t)= last2 bytes of nonce used for encryption 3 if (length == 0 || length > max_length) { 4 return -1; 5 } 6 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 7 if (conn == nullptr) { 8 return -1; 9 } 10 pthread_mutex_lock(conn->mutex); 11 // Sizeof(uint16_t) necessary for last2 bytes of base nonce 12 VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); 13 packet[0] = NET_PACKET_CRYPTO_DATA; 14 memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof( uint16_t));// Copies the last2 bytes of the nonce into the packet 15 // Uses the sending key and base nonce(both of the local peer) to encrypt the payload 16 const int len = encrypt_data_symmetric(conn->send_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); 17 if (len + 1 + sizeof(uint16_t) != SIZEOF_VLA(packet)) { 18 pthread_mutex_unlock(conn->mutex); 19 return -1; 20 } 21 increment_nonce(conn->sent_nonce);// Increment nonce for next packet 22 pthread_mutex_unlock(conn->mutex); 23 return send_packet_to(c, crypt_connection_id, packet, SIZEOF_VLA(packet)); 24 } Listing 4.26: send_data_packet(): encryption based on XSalsa20-Poly1305

67 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

1 static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint8_t *data, const uint8_t *packet, uint16_t length) { 2 const uint16_t crypto_packet_overhead = 1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE; 3 // Length is1(packet kind)+ encrypted payload+ MAC 4 if (length <= crypto_packet_overhead || length > MAX_CRYPTO_PACKET_SIZE) { 5 return -1; 6 } 7 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 8 if (conn == nullptr) { 9 return -1; 10 } 11 uint8_t nonce[CRYPTO_NONCE_SIZE]; 12 // Copy base nonce from remote peer (= recv_nonce) into nonce 13 memcpy(nonce, conn->recv_nonce, CRYPTO_NONCE_SIZE); 14 uint16_t num_cur_nonce = get_nonce_uint16(nonce); 15 uint16_t num; 16 net_unpack_u16(packet + 1, &num); 17 uint16_t diff = num - num_cur_nonce; 18 increment_nonce_number(nonce, diff); 19 // Uses the receiving key and base nonce(both of the remote peer) to decrypt the payload 20 int len = decrypt_data_symmetric(conn->recv_key, nonce, packet + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), data); 21 if((unsigned int) len != length - crypto_packet_overhead) { 22 return -1; 23 } 24 if (diff > DATA_NUM_THRESHOLD * 2) { 25 increment_nonce_number(conn->recv_nonce, DATA_NUM_THRESHOLD); 26 } 27 return len; 28 } Listing 4.27: handle_data_packet(): decryption based on XSalsa20-Poly1305

4.4.1. Testing UDP Packet Loss with flakynet (XSalsa20-Poly1305)

This implementation uses ChaCha20-Poly1305 to encrypt the handshake packets by calling functions of the Noise-C library. XSalsa20-Poly1305 encryption is used to encrypt messages after a successful handshake by using the keys retrieved from the NoiseHandshakeState. This enables the use of the already-existing UDP packet loss mechanism of c-toxcore. Testing with minitox was performed as described in section 4.3.2. The of this implementation attempt was to gain a Noise-based handshake which copes with UDP packet loss, hence the resulting c-toxcore library was again tested with flakynet. This time a successful handshake and exchange of encrypted messages is also possible with up to 50% packet loss for both peers (i.e. starting both minitox instances with flakynet configured to 50% packet loss). If packet loss is configured between 60 and 70 percent it takes the peers much longer to perform a successful handshake, additionally the connection is lost from time to time and then a new handshake needs to be performed. 70 percent packet loss was also tested with minitox instances built with the non-Noise Tox handshake and this leads to the same behavior. This means that it is too much packet loss for the Tox protocol in general and not a problem introduced with the Noise-based handshake. Therefore a KCI-resistant handshake was implemented based on Noise. The resulting keys for symmetric encryption are used with XSalsa20-Poly1305 to exchange messages in the transport phase of the protocol. Note that it was not explicitly tested if this implementation is able to successfully process out-of-order transport messages. Since this solution uses the already-existing UDP loss func- tionality of toxcore, this means that the already-existing out-of-order functionality is used.

68 Chapter 4. Design and Implementation of a KCI-resistant Tox Handshake based on Noise

Therefore this implementation should also be able to handle packets that were not received in order.

69 5. Conclusion and Future Work

Secure messaging can be enabled through different architectures, each with their own set of advantages and disadvantages. Tox is an example for a P2P protocol that provides E2EE. This thesis examines the Tox protocol, more specifically Tox’ handshake, which is in place to create a channel. The basis for E2EE is an AKE during Tox’ handshake. This custom AKE provides a variety of security guarantees like forward secrecy and deniability, but lacks KCI-resistance. In theory it was shown that Tox is vulnerable to multiple attacks based on KCI. However, these attacks are not as easy to conduct in practice as suggested in the initial report by Jason A. Donenfeld [Don17a]. This is due to the cookie phase of Tox’ handshake that is carried out before the AKE starts. This cookie phase uses a shared secret based on both parties DHT key pairs. Due to the use of these DHT keys an adversary Mallory is unable to initiate or respond to a handshake on their own because they are not able to craft valid cookie request/response packets. Therefore it is necessary for Mallory, who compromised the long-term private key of Alice and wants to masquerade as Bob to Alice, to interfere with a Tox handshake between Alice and Bob after the cookie phase. Additionally it’s required for Mallory to know the long-term public key of the party they want to impersonate. Further this party must be a Tox friend of Alice. The plan was to create a PoC attack program, but due to this discovered difficulties it could not be completed for this thesis and is postponed to future work (cf. section 3.5.1). The Noise Protocol Framework was used to design a new KCI-resistant handshake for Tox. The adopted Noise protocol provides the same security properties as the old handshake. The Noise-C library was used to implement this new handshake in toxcore. At first it was considered to apply the Noise KK handshake pattern because it was assumed that both parties have pre-knowledge of the other’s long-term public key. However the responder doesn’t have access to the initiators public key in toxcore where it is necessary to initialize the NoiseHandshakeState. Instead of the KK pattern the IK pattern was used to implement the Noise-based handshake. Both patterns provide the same security properties, but in IK only the initiator has pre-knowledge of the responders public key. Therefore the initiator sends their public key to the responder during the handshake. This message is encrypted and for that reason the IK-based handshake still provides deniability as a property. Another discovery is that Noise-C in its current state is not suited for use with UDP because it cannot handle packets that arrive out-of-order (cf. section 4.3.2). This was solved by adding two functions to Noise-C to retrieve the shared secret session keys after a successful handshake. This makes it possible to use these session keys with the already-existing XSalsa20-Poly1305 encryption/decryption functions. Toxcore already provides functionality based on XSalsa20 encryption to cope with UDP packet loss and out-of-order messages during the transport phase of a Tox connection. For that reason it was preferred to reuse this functionality, instead of reimplementing it for ChaCha20-based encryption with 8-byte nonces (in contrast to 24-bytes nonces used in XSalsa20). One additional function to initialize a NoiseHandshakeState was added in toxcore. Besides that only the present handshake-related functions were adapted to implement the Noise-based handshake. The cookie phase of the handshake remains unchanged and therefore still uses shared secrets calculated with a single ECDH computation.

70 Chapter 5. Conclusion and Future Work

Overall this thesis successfully demonstrated that it is possible to adopt a Noise protocol instead of the custom AKE in Tox. This Noise-based handshake is able to cope with UDP packet loss respectively out-of-order messages, which is crucial for a P2P protocol. Further- more it provides the same security properties as the old handshake, but is now based on a formally-verified AKE construction and adds KCI-resistance.

5.1. Future Work

For future work it is planned to create a PoC attack program that practically demonstrates a MitM attack based on KCI (cf. section 3.5.1). Moreover the implementation of the new Noise-based handshake as presented in this thesis is not intended for use in production and should be further improved. The KCI-vulnerable handshake was designed to successfully establish a connection between two peers even if both try to initiate a connection at the same time. For the Noise-based handshake it is necessary to differentiate between initiator and responder. As described in chapter 4 it is possible to use the current Net_crypto structure to accomplish this differentiation. However, this is not ideal and could lead to problems in practical use (i.e. toxcore may behave different in realistic network conditions to the test setup used during this thesis). Therefore it is recommended to further test this Noise-based implementation in regular use to identify possible shortcomings. Apart from the initiator/responder differentiation, the error handling during the handshake should be thoroughly tested and evaluated as well. At the moment the Noise-based handshake is implemented by using the Noise-C library. Noise-C supports a wide range of Noise handshake patterns and cryptographic primitives that are not necessary for the Tox handshake. Instead of using the library, the IK pattern could be implemented explicitly for use in Tox. This would remove Noise-C as a dependency for toxcore and therefore reduce the number of possibly vulnerable source lines of code. The WireGuard VPN for example, which implemented the Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s protocol directly, is realized in less than 4 000 lines of code [Don17b]. In comparison, only the Noise protocol part of the Noise-C library is implemented in more than 3 500 lines of code. When implementing the IK pattern directly in toxcore, it should be evaluated if it is necessary to use two different ciphers (i.e. ChaCha20 during the AKE and XSalsa20 during the transport phase), or if it’s feasible to only use ChaCha20 (since XSalsa20 is not supported by Noise). Additionally the prologue used in the Noise-based handshake is just the full Noise protocol name, instead information only known to both Tox peers could be used. Furthermore the current implementation of the Noise-based handshake is not compatible with the old KCI-vulnerable handshake. It may be desirable to add a mechanism to make it backwards compatible to enable communications also with old toxcore library versions. This may be part of a bigger redesign of Tox’ handshake. Eventually Tox’ handshake could be restructured to support the use of the KK pattern instead of IK. In the KCI-vulnerable handshake the ephemeral X25519 session keys were transferred en- crypted, in the Noise-based handshake these are sent in cleartext (as per the design of the Noise framework). This is no vulnerability, but they could also be sent encrypted. In NTCP2 for example, cleartext ephemeral keys are obfuscated using AES encryption [vil18].

71 Chapter 5. Conclusion and Future Work

From a security point-of-view the following Noise-supported features could be added to the Noise-based handshake: • Session re-keying1 (e.g. after a defined number of messages) with the result that shared session key compromise can not be used to decrypt older messages • Usage of an optional additional pre-shared 256-bit symmetric key to mitigate any future advances in quantum computing (cf. [Per18] and [Don17b]) There is also possible future work regarding Tox besides the handshake: • Full security analysis of the protocol (based on the detailed description of the handshake in section 2.4) and its implementation in toxcore • Formal verification of all security properties (cf. sections 2.4.1 and 4.1.1)

1There is also an open issue on GitHub "Implement session rekeying #238": https://github.com/ TokTok/c-toxcore/issues/238

72 Bibliography

[Ber05] Daniel J. Bernstein. The Poly1305-AES Message-Authentication Code. In Inter- national Workshop on Fast Software Encryption, pages 32–49. Springer, 2005. 2, 17 [Ber06] Daniel J. Bernstein. Curve25519: new Diffie-Hellman speed records. In Inter- national Workshop on Public Key Cryptography, pages 207–228. Springer, 2006. 2, 11, 16, 79 [Ber11] Daniel J. Bernstein. Extending the Salsa20 Nonce. In Workshop record of Symmetric Key Encryption Workshop, volume 2011, 2011. 2, 17 [Ber14] Daniel J. Bernstein. [Cfrg] 25519 naming. https://mailarchive.ietf. org/arch/msg/cfrg/-9LEdnzVrE5RORux3Oo_oDDRksU/, 2014. Ac- cessed at 07.06.2020. 11 [Ber16] Daniel J. Bernstein. NaCl: Networking and Cryptography Library. https: //nacl.cr.yp.to/index.html, 2016. Accessed at 04.07.2020. 16 [BLS12] Daniel J. Bernstein, Tanja Lange, and Peter Schwabe. The security impact of a new cryptographic library. In International Conference on Cryptology and Information Security in Latin America, pages 159–176. Springer, 2012. 16 [BMO+20] Richard Barnes, Jon Millican, Emad Omara, Katriel Cohn-Gordon, and Raphael Robert. The Messaging Layer Security (MLS) Protocol (Draft). https:// datatracker.ietf.org/doc/draft-ietf-mls-protocol/, 2020. Ac- cessed at 17.06.2020. 4 [BMS20] Colin Boyd, Anish Mathuria, and Douglas Stebila. Protocols for Authentication and Key Establishment, volume 2. Springer, 2020. 8, 9, 10, 11, 79 [BOS+19] Daniel Balchasan, Michal Ozaniak, Yoav Schwartz, Nicolai Strøm Steffensen, Samant Khajuria, and Lene Sørensen. ATHiCC: An Anonymous, Asynchronous, Serverless Instant Messaging Protocol. In Proceedings of the 52nd Hawaii In- ternational Conference on System Sciences, 2019. 4, 6, 7, 79 [BWJM97] Simon Blake-Wilson, Don Johnson, and Alfred Menezes. Key Agreement Pro- tocols and their Security Analysis. In IMA International Conference on Cryp- tography and Coding, pages 30–45. Springer, 1997. 31 [BWM98] Simon Blake-Wilson and Alfred Menezes. Authenticated Diffe-Hellman Key Agreement Protocols. In International Workshop on Selected Areas in Cryptog- raphy, pages 339–361. Springer, 1998. 8 [CK01] Ran Canetti and Hugo Krawczyk. Analysis of Key-Exchange Protocols and Their Use for Building Secure Channels. In International Conference on the Theory and Applications of Cryptographic Techniques, pages 453–474. Springer, 2001. 12 [Cle19] Jessica Clement. Number of daily active WhatsApp Status users from 1st quarter 2017 to 1st quarter 2019 (in millions). https://www.statista. com/statistics/730306/-status-dau/, 2019. Accessed at 04.07.2020. 1

73 Bibliography

[CPZ19] Melissa Chase, Trevor Perrin, and Greg Zaverucha. The Signal Private Group System and Anonymous Credentials Supporting Efficient Verifiable Encryption. Cryptology ePrint Archive, Report 2019/1416, 2019. Accessed at 17.06.2020. https://eprint.iacr.org/2019/1416. 4 [Den19] Frank Denis. libsodium. https://github.com/jedisct1/libsodium/ blob/8b70853c8dbbb9fbe7701b502e00066307a8f51d/README. markdown, 2019. Accessed at 02.07.2020. 16 [DH76] Whitfield Diffie and Martin Hellman. New Directions in Cryptography. IEEE transactions on Information Theory, 22(6):644–654, 1976. 10 [DM17] Jason A. Donenfeld and Kevin Milner. Formal Verification of the Wireguard Protocol. https://www.wireguard.com/papers/wireguard-formal- verification.pdf, 2017. Accessed at 17.06.2020. 4 [Don17a] Jason A. Donenfeld. Tox Handshake Vulnerable to KCI. https://github. com/TokTok/c-toxcore/issues/426, 2017. Accessed at 04.07.2020. 2, 32, 70 [Don17b] Jason A. Donenfeld. WireGuard: Next Generation Kernel Network Tunnel. In Proceedings 2017 Network and Distributed System Security Symposium. , 2017. 4, 25, 43, 71, 72 [DP18] Benjamin Dowling and Kenneth G. Paterson. A Cryptographic Analysis of the WireGuard Protocol. In International Conference on Applied Cryptography and Network Security, pages 3–21. Springer, 2018. 4 [DRS19] Benjamin Dowling, Paul Rösler, and Jörg Schwenk. Flexible Authenticated and Confidential Channel Establishment (fACCE): Analyzing the Noise Protocol Framework. https://eprint.iacr.org/2019/436.pdf, 2019. Accessed at 16.04.2020. 30 [EM19] Ksenia Ermoshina and Francesca Musiani. "Standardising by running code": the Signal protocol and de facto standardisation in end-to-end encrypted messaging. Internet Histories, 3(3-4):343–363, 2019. 1 [Gir19] Guillaume Girol. Master Thesis: Formalizing and Verifying the Secu- rity Protocols from the Noise Framework. https://www.research- collection.ethz.ch/bitstream/handle/20.500.11850/332859/ 1/Girol_Guillaume.pdf, 2019. Accessed at 04.07.2020. 2, 30 [Gre13] Glenn Greenwald. NSA collecting phone records of millions of Verizon customers daily. https://www.theguardian.com/world/2013/jun/ 06/nsa-phone-records-verizon-court-order, 2013. Accessed at 04.07.2020. 1 [Gre16] Andy Greenberg. Meet , the Anarchist Bringing Encryp- tion to All of Us. https://www.wired.com/2016/07/meet-moxie- marlinspike-anarchist-bringing-encryption-us/, 2016. Accessed at 15.06.2020. 1 [Har15] Tamino P.S.M. Hartmann. Master Thesis: Tinzenite: Encrypted Peer to Peer File Synchronization via the Tox Protocol. http://dbis.eprints.uni- ulm.de/1334/, October 2015. Accessed at 04.07.2020. 3 [HAWSC18] Mathias Hall-Andersen, David Wong, Nick Sullivan, and Alishah Chator. nQUIC: Noise-based QUIC Packet Protection. In Proceedings of the Work-

74 Bibliography

shop on the , Performance, and Interoperability of QUIC, pages 22–28, 2018. 5 [Hei13] Heise Online. NSA-Skandal: Das Jahr 2013. https://www.heise.de/ extras/timeline-2013, 2013. Accessed at 04.07.2020. 1 [HGFS15] Clemens Hlauschek, Markus Gruber, Florian Fankhauser, and Christian Schanes. Prying Open Pandora’s Box: KCI Attacks against TLS. In 9th USENIX Workshop on Offensive Technologies (WOOT 15), 2015. 4, 32 [Hod20] Matthew Hodgson. On Privacy versus Freedom. https://matrix.org/ /2020/01/02/on-privacy-versus-freedom, 2020. Accessed at 15.06.2020. 2, 7 [Hub19] Ryan Huber. Introducing Nebula, the open source global overlay net- work from Slack. https://slack.engineering/introducing- nebula-the-open-source-global-overlay-network-from- slack-884110a5579?gi=e95151169c48, 2019. Accessed at 15.04.2020. 25 [Imp19] Impyy et al. About - The Tox Project. https://tox.chat/about.html, 2019. Accessed at 04.07.2020. 13 [Jel16] Alexander Jelinek. Security aspects of secure messaging. http://pub.fh- campuswien.ac.at/obvfcwhs/content/titleinfo/1808118, 2016. Accessed at 04.07.2020. 3 [KE10] Hugo Krawczyk and Pasi Eronen. RFC7748: HMAC-based Extract-and- Expand Key Derivation Function (HKDF). https://www.ietf.org/rfc/ rfc5869.txt, 2010. Accessed at 20.04.2020. 44 [KNB19] Nadim Kobeissi, Georgio Nicolas, and Karthikeyan Bhargavan. Noise Explorer: Fully Automated Modeling and Verification For Arbitrary Noise Protocols. In 2019 IEEE European Symposium on Security and Privacy (EuroS&P), pages 356–370. IEEE, 2019. 2, 30 [Kra05] Hugo Krawczyk. HMQV: A High-Performance Secure Diffie-Hellman Protocol. In Annual International Cryptology Conference, pages 546–566. Springer, 2005. 4, 32 [Lev16] Yasha Levine. Spy-funded privacy tools (like Signal and Tor) are not going to protect us from President Trump. https://surveillancevalley. com/blog/government-backed-privacy-tools-are-not-going- to-protect-us-from-president-trump, 2016. Accessed at 15.06.2020. 1 [LHT16] Adam Langley, Mike Hamburg, and Sean Turner. RFC7748: Elliptic Curves for Security. https://www.ietf.org/rfc/rfc7748.txt, 2016. Accessed at 17.04.2020. 15, 28, 44 [LLM07] Brian LaMacchia, Kristin Lauter, and Anton Mityagin. Stronger Security of Authenticated Key Exchange. In International conference on provable security, pages 1–16. Springer, 2007. 4 [LMQ+03] Laurie Law, Alfred Menezes, Minghua Qu, Jerry Solinas, and Scott Vanstone. An Efficient Protocol for Authenticated Key Agreement. Designs, Codes and Cryptography, 28(2):119–134, 2003. 32 [LN15] Adam Langley and Yael Nir. RFC7539: ChaCha20 and Poly1305 for IETF

75 Bibliography

Protocols. https://www.ietf.org/rfc/rfc7539.txt, 2015. Accessed at 17.04.2020. 28 [Mar16a] Moxie Marlinspike. Reflections: The ecosystem is moving. https://signal. org/blog/the-ecosystem-is-moving/, 2016. Accessed at 15.06.2020. 1, 2 [Mar16b] Moxie Marlinspike. WhatsApp’s Signal Protocol integration is now complete. https://signal.org/blog/whatsapp-complete/, 2016. Accessed at 04.07.2020. 1 [Mat19] Matrix. We have discovered and addressed a security breach. (Updated 2019-04- 12). https://matrix.org/blog/2019/04/11/we-have-discovered- and-addressed-a-security-breach-updated-2019-04-12, 2019. Accessed at 04.07.2020. 7 [Mic19a] Microsoft. Microsoft-Datenschutzbestimmungen. https://privacy. microsoft.com/de-de/privacystatement/, 2019. Accessed at 04.07.2020. 1 [Mic19b] Microsoft. Skype Connect Terms for Non U.S. Customers - 15. Your Confiden- tial Information And Your Privacy. https://www.skype.com/en/legal/ tou-connect/, 2019. Accessed at 04.07.2020. 1 [MP16] Moxie Marlinspike and Trevor Perrin. The X3DH Key Agreement Pro- tocol. https://signal.org/docs/specifications/x3dh/x3dh.pdf, 2016. Accessed at 18.06.2020. 1 [MP17] Moxie Marlinspike and Trevor Perrin. The Sesame Algorithm: Session Manage- ment for Asynchronous Message Encryption. https://signal.org/docs/ specifications/sesame/sesame.pdf, 2017. Accessed at 18.06.2020. 1 [MVOV96] Alfred J. Menezes, Paul C. Van Oorschot, and Scott A Vanstone. Handbook of Applied Cryptography. CRC press, 1996. 8 [nur18a] nurupo et al. Tox - Frequently Asked Questions. https://wiki.tox. chat/users/faq, 2018. Accessed at 04.07.2020. 13 [nur18b] nurupo et al. Tox Wiki - Technical FAQ. https://wiki.tox.chat/users/ techfaq, 2018. Accessed at 04.07.2020. 14 [nur19] nurupo et al. Tox - A New Kind of Instant Messaging. https://tox.chat/ index.html, 2019. Accessed at 04.07.2020. 13 [Per16] Trevor Perrin. The XEdDSA and VXEdDSA Signature Schemes. https:// signal.org/docs/specifications/xeddsa/xeddsa.pdf, 2016. Ac- cessed at 18.06.2020. 1 [Per17] Trevor Perrin. The Noise Protocol Framework. https://media. ccc.de/v/34c3-9222-the_noise_protocol_framework resp. https://cdn.media.ccc.de/congress/2017/slides-pdf/34c3- 9222-the_noise_protocol_framework.pdf, 2017. Presentation and slides from 34C3 conference, 28.12.2017. Accessed at 06.06.2020. 12, 13, 28, 79 [Per18] Trevor Perrin. The Noise Protocol Framework. https://noiseprotocol. org/noise.html, 2018. Revision 34, 07.11.2018, official/unstable. Accessed at 04.07.2020. 2, 25, 26, 27, 28, 29, 43, 61, 72, 79, 80 [PG13] Laura Poitras and Glenn Greenwald. NSA whistleblower Edward - den: ’I don’t want to live in a society that does these sort of things’ - video. https://www.theguardian.com/world/video/2013/jun/09/

76 Bibliography

nsa-whistleblower-edward-snowden-interview-video, 2013. Ac- cessed at 04.07.2020. 1 [PM16] Trevor Perrin and Moxie Marlinspike. The . https://signal.org/docs/specifications/doubleratchet/ doubleratchet.pdf, 2016. Accessed at 18.06.2020. 1 [Rob17] Robin Linden and sudden6 and zoff. Tox: communicate safe ev- erywhere. https://github.com/zoff99/ToxCon2017/tree/ da4532cab2e7d6aeca5751e5e41d347f0bd4193c, 2017. Accessed at 02.07.2020. 13 [Rog02] Phillip Rogaway. Authenticated-Encryption with Associated-Data. In Proceed- ings of the 9th ACM Conference on Computer and Communications Security, pages 98–107, 2002. 15, 26 [SA15] Markku-Juhani Saarinen and Jean-Philippe Aumasson. RFC7693: The BLAKE2 Cryptographic Hash and Message Authentication Code (MAC). https://www.ietf.org/rfc/rfc7693.txt, 2015. Accessed at 17.04.2020. 28 [SD18] Andris Suter-Dörig. Bachelor Thesis: Formalizing and Verifying the Secu- rity Protocols from the Noise Framework. https://ethz.ch/content/ dam/ethz/special-interest/infk/inst-infsec/information- security-group-dam/research/software/noise_suter- doerig.pdf, 2018. Accessed at 04.07.2020. 30 [SH19] Michael Schliep and Nicholas Hopper. End-to-End Secure Mobile Group Mes- saging with Conversation Integrity and Deniability. In Proceedings of the 18th ACM Workshop on Privacy in the Electronic Society, pages 55–73, 2019. 4 [Sig19] Signal. Signal Terms & Privacy Policy. https://signal.org/legal/, 2019. Accessed at 04.07.2020. 6 [Sky17] SkyzohKey. [DRAFT] Toxcore Threat Model. https://github.com/ TokTok/spec/issues/50, 2017. Accessed at 04.07.2020. 32 [Str06] Maurizio Adriano Strangio. On the Resilience of Key Agreement Protocols to Key Compromise Impersonation. In European Public Key Infrastructure Work- shop, pages 233–247. Springer, 2006. 4, 31, 32 [Str07] Maurizio Adriano Strangio. Revisiting an Efficient Elliptic Curve Key Agree- ment Protocol. IACR Cryptology ePrint Archive, 2007:81, 2007. 4 [The20] The Lightning Network. BOLT #8: Encrypted and Authenticated Transport. https://github.com/lightningnetwork/lightning-rfc/blob/ fb7102e034c436954e33635a7ce8523e03370ad7/08-transport.md, 2020. Accessed at 15.04.2020. 25 [Tok18] TokTok. c-toxcore/README.md. https://github.com/TokTok/c- toxcore/blob/b4cf9808e972952c003c80b9e766b8e66e671703/ README.md, 2018. Accessed at 04.07.2020. 32 [Tok20] TokTok. The Tox Protocol Reference. https://github.com/TokTok/ spec/blob/bff772e0eca4666b20f9cc1ce001679caa6252bd/spec. md, 2020. Accessed at 19.04.2020. 2, 14, 16, 17, 18, 19, 20, 21, 22, 79, 80, 83 [UDB+15] Nik Unger, Sergej Dechand, Joseph Bonneau, Sascha Fahl, Henning Perl, Ian Goldberg, and Matthew Smith. SoK: Secure Messaging. In 2015 IEEE Sym-

77 Bibliography

posium on Security and Privacy, pages 232–249. IEEE, 2015. 3, 7, 8, 9, 10, 79 [UG15] Nik Unger and Ian Goldberg. Deniable Key Exchanges for Secure Messaging. In Proceedings of the 22nd acm sigsac conference on computer and communications security, pages 1211–1223, 2015. 3 [UG18] Nik Unger and Ian Goldberg. Improved Strongly Deniable Authenticated Key Exchanges for Secure Messaging. Proceedings on Privacy Enhancing Technolo- gies, 2018(1):21–66, 2018. 3 [Ung15] Nik Unger. Master Thesis: Deniable Key Exchanges for Secure Messaging. https://uwspace.uwaterloo.ca/handle/10012/9406, 2015. Accessed at 17.06.2020. 3 [vil18] villain. NTCP2. https://geti2p.net/spec/ntcp2, 2018. Accessed at 04.07.2020. 4, 25, 71 [Vog16] Markus Vogl. Evaluation of the Secure IM Landscape: Extended comparison of features and security aspects. https://xn--4ca9a.eu/bac.pdf, 2016. Accessed at 04.07.2020. 3 [Wea16] Rhys Weatherley. Noise-C Documentation. https://rweather.github. io/noise-c/index.html, 2016. Accessed at 31.05.2020. 53 [Wha17] WhatsApp Inc. WhatsApp Encryption Overview - Technical white pa- per. https://www.whatsapp.com/security/WhatsApp-Security- Whitepaper.pdf, 2017. Accessed at 04.07.2020. 25 [Wha20] WhatsApp. Two Billion Users – Connecting the World Privately. https://blog.whatsapp.com/two-billion-users-connecting- the-world-privately, 2020. Accessed at 21.06.2020. 1 [Wil74] Malcolm J. Williamson. Non–secret encryption using a finite field. Technical report, Technical report, CESG, 1974. 10 [Wil13] Andreas Wilkens. Bericht: US-Regierung zapft Kundendaten von Internet- Firmen an. https://www.heise.de/newsticker/meldung/Bericht- US-Regierung-zapft-Kundendaten-von-Internet-Firmen-an- 1884264.html, 2013. Accessed at 04.07.2020. 1 [Wu19] Peter Wu. Master Thesis: Analysis of the WireGuard protocol. https: //lekensteyn.nl/files/pwu-wireguard-thesis-final.pdf, June 2019. Accessed at 19.04.2020. 4, 43

78 List of Figures

2.1. Illustration of centralized, decentralized and distributed networks (cf. [BOS+19])6 2.2. Session keys are protected from long-term key compromise (cf. [UDB+15]) . .9 2.3. Diffie-Hellman key agreement (cf. [BMS20]) ...... 10 2.4. Curve25519 data flow from secret keys through public keys to a shared secret (cf. [Ber06]) ...... 11 2.5. Phases of a secure channel protocol (cf. [Per17]) ...... 12 2.6. Negotiation and AKE happen during the handshake phase of a secure channel protocol (cf. [Per17]) ...... 13 2.7. An example Tox ID (cf. [Tok20]) ...... 14 2.8. Cookie request packet from peer A (145 bytes) ...... 17 2.9. Cookie from peer B (112 bytes) ...... 17 2.10. Cookie response packet from peer B (161 bytes) ...... 18 2.11. Handshake packet from peer A (385 bytes) ...... 18 2.12. Encrypted data packet from peer A (19 bytes + variable length payload) . . . 18 2.13. Tox ideal handshake scenario (cf. [Tok20]) ...... 19 2.14. Tox realistic handshake scenario (cf. [Tok20]) ...... 20 2.15. In the Noise KK handshake pattern both parties have pre-knowledge of the other’s static public key. (cf. [Per18]) ...... 27 2.16. In the Noise IK handshake pattern the initiator has pre-knowledge of the re- sponder’s static public key. (cf. [Per18]) ...... 27 2.17. Noise protocol components (cf. [Per17]) ...... 28

4.1. Noise-based handshake packet from initiator A (XSalsa20-based transport phase; 409 bytes) ...... 48 4.2. Noise-based handshake packet from responder B (XSalsa20-based transport phase; 361 bytes) ...... 48

79 List of Tables

2.1. Handshake-relevant packet kinds and their byte representation (cf. [Tok20]) . 17

4.1. Noise IK handshake pattern’s payload security properties (cf. [Per18] and section 2.5.3) ...... 43 4.2. Software and libraries used to implement and test the Noise-based Tox handshake 49

A.1. All Tox packet kinds and their byte representation (cf. [Tok20]) ...... 83

80 Listings

4.1. Crypto_Connection struct as defined in net_crypto.c ...... 51 4.2. New_Connection struct as defined in net_crypto.h ...... 52 4.3. HANDSHAKE_PACKET_LENGTH as defined in net_crypto.c (385 bytes) . . . . 52 4.4. Include Noise-C header file and definition of CRYPTO_NOISE_PROTOCOL_NAME in net_crypto.h ...... 54 4.5. Adapted Crypto_Connection struct (ChaCha20-based transport phase) . 54 4.6. Adapted New_Connection struct (ChaCha20-based transport phase) . . . . 54 4.7. Different packet lengths for initiator and responder in net_crypto.c ...... 55 4.8. Creation of a NoiseHandshakeState as initiator ...... 55 4.9. initialize_handshake() function to set prologue, static secret key of the local peer and static public key of the remote peer ...... 55 4.10. Initialization of the NoiseHandshakeState object ...... 56 4.11. Initiator starts the handshake in handle_packet_connection() ..... 56 4.12. Responder starts the handshake in handle_new_connection_handshake() 56 4.13. create_crypto_handshake() is called by both peers to create a hand- shake packet ...... 57 4.14. handle_crypto_handshake() is called by both peers when a handshake packet is received ...... 58 4.15. Splitting the NoiseHandshakeState in two NoiseCipherState objects 59 4.16. send_data_packet(): encryption based on ChaCha20-Poly1305 ...... 60 4.17. handle_data_packet(): decryption based on ChaCha20-Poly1305 . . . . 60 4.18. Function added to handshakestate.c of Noise-C ...... 62 4.19. Function added to symmetricstate.c of Noise-C ...... 63 4.20. Adapted Crypto_Connection struct (XSalsa20-based transport phase) . . 63 4.21. Adapted New_Connection struct (XSalsa20-based transport phase) . . . . 64 4.22. Different packet lengths for initiator and responder in net_crypto.c (including a base nonce) ...... 64 4.23. create_crypto_handshake() with base nonce ...... 64 4.24. handle_crypto_handshake() with base nonce ...... 65 4.25. NoiseHandshakeState is split in two arrays instead of two NoiseCipherState objects ...... 67 4.26. send_data_packet(): encryption based on XSalsa20-Poly1305 ...... 67 4.27. handle_data_packet(): decryption based on XSalsa20-Poly1305 . . . . . 68

A.1. Include Noise-C in c-toxcore/CMakeList.txt ...... 86

81 Lists

2.1. Notation used for (cryptographic) values and operations in chapter 2 . . . . . 15 2.2. Message flow and computations during an "ideal" Tox handshake ...... 22

3.1. Tox AKE between peers A and B attacked by adversary M to impersonate B to A ...... 34 3.2. MitM attack from M on Tox’ AKE between peers A and B by exploiting KCI 36

82 A. Appendix

A.1. Tox protocol packets

Byte value Packet kind Length Packet format 0x00 Ping Request 0x01 Ping Response 0x02 Nodes Request 0x04 Nodes Response 0x18 Cookie Request 145 bytes see figure 2.8 (no packet) Cookie 112 bytes see figure 2.9 0x19 Cookie Response 161 bytes see figure 2.10 0x1a Crypto Handshake 385 bytes see figure 2.11 0x1b Crypto Data 19 bytes + variable payload see figure 2.12 0x20 DHT Request 0x21 LAN Discovery 0x80 Onion Request 0 0x81 Onion Request 1 0x82 Onion Request 2 0x83 Announce Request 0x84 Announce Response 0x85 Onion Data Request 0x86 Onion Data Response 0x8c Onion Response 3 0x8d Onion Response 2 0x8e Onion Response 1 0xf0 Bootstrap Info

Table A.1.: All Tox packet kinds and their byte representation (cf. [Tok20])

83 Appendix A. Appendix

A.2. Implementation Source Code

The complete source code of the implementation can be found on GitHub (cf. section 4.2): • Repository goldroom/c-toxcore: https://github.com/goldroom/c-toxcore – Branch tb_noise_handshake: https://github.com/goldroom/c-toxcore/ tree/tb_noise_handshake – Branch tb_noise_handshake_IK: https://github.com/goldroom/c-toxcore/ tree/tb_noise_handshake_IK – Branch tb_noise_handshake_IK_noise_patch: https://github.com/goldroom/ c-toxcore/tree/tb_noise_handshake_IK_noise_patch • Repository goldroom/noise-c: https://github.com/goldroom/noise-c – Branch master: https://github.com/goldroom/noise-c – Branch split_key_patch: https://github.com/goldroom/noise-c/tree/ split_key_patch • Repository goldroom/minitox: https://github.com/goldroom/minitox – Branch master: https://github.com/goldroom/minitox – Branch: tb_minitox_adaptions: https://github.com/goldroom/minitox/ tree/tb_minitox_adaptions – The minitox repository was initially hosted on https://git.fh-campuswien. ac.at/c1810537022/minitox. This was changed to have all repositories on a single platform.

84 Appendix A. Appendix

A.3. Building libsodium

Download libsodium stable from https://download.libsodium.org/libsodium/releases/ (i.e. libsodium-1.0.18-stable.tar.gz) and extract the archive. Build system requirements (packages that need to be installed): autotools CLI commands to build and install libsodium (MacOS and Debian Linux): • cd libsodium-1.0.18-stable • ./configure • make && make check • sudo make install • sudo ldconfig – On (Debian) Linux, for any manually installed library, running the ldconfig command is required in order to make the dynamic linker aware of the new library. Installation directory (on MacOS 10.15.3/Catalina and Debian 10/Buster): /usr/local /lib/

A.4. Building Noise-C

Build system requirements (packages that need to be installed): autoconf, automake, bison and flex CLI commands to build and install Noise-C (MacOS and Debian Linux): • git clone https://github.com/goldroom/noise-c.git • cd noise-c • git checkout -b split_key_patch origin/split_key_patch – This is only necessary to test the final XSalsa20-based implementation (see section 4.4). The ChaCha20-based implementation is based on the master branch. • ./configure • make – To build c-toxcore with Noise-C on Debian/Linux it is necessary to compile Noise using the gcc flag -fPIC and call make like this: ∗ make CFLAGS=’-g -O2 -pthread -fPIC’ • make check • sudo make install • sudo ldconfig – On (Debian) Linux, for any manually installed library, running the ldconfig command is required in order to make the dynamic linker aware of the new library. Installation directory (on MacOS 10.15.3/Catalina and Debian 10/Buster): /usr/local /lib/libnoiseprotocol.a Public API header file: /usr/local/include/noise/protocol.h

85 Appendix A. Appendix

A.5. Building c-toxcore

Library dependencies (without toxav): libsodium Supported compilers: GCC, Clang and MinGW Build system requirements (packages that need to be installed): cmake and pkg-config CLI commands to build and install c-toxcore (MacOS and Debian Linux): • git clone https://github.com/goldroom/c-toxcore.git • cd c-toxcore • git checkout -b tb_noise_handshake_IK_noise_patch origin/tb_noise_handshake_IK_noise_patch – This is necessary to test the final XSalsa20-based implementation (see section 4.4). The ChaCha20-based implementation is contained in the tb_noise_handshake_IK branch. • mkdir _build && cd _build • cmake -D AUTOTEST=ON -D BOOTSTRAP_DAEMON=OFF -D BUILD_TOXAV=OFF .. – Bootstrap daemon and toxav are not necessary for the handshake • make • sudo make install • sudo ldconfig – On (Debian) Linux, for any manually installed library, running the ldconfig command is required in order to make the dynamic linker aware of the new library. Installation directory (on MacOS 10.15.3/Catalina and Debian 10/Buster): /usr/local /lib/libtoxcore.a Public API header file: /usr/local/include/tox/tox.h

A.5.1. Building c-toxcore with Noise-C

To build c-toxcore with Noise-C (to be able to use functions from Noise-C), one needs to be changed and an additional line needs to be added to toxcore’s CMakeLists.txt (see listing A.11). Otherwise building of toxcore aborts with fatal error: ’noise/protocol.h’ file not found. This was tested on MacOS 10.15.3/Catalina and Debian 10/Buster.

L159 - set(toxcore_LINK_MODULES ${toxcore_LINK_MODULES} ${ LIBSODIUM_LIBRARIES}) L159 + set(toxcore_LINK_MODULES ${toxcore_LINK_MODULES} ${ LIBSODIUM_LIBRARIES} "/usr/local/lib/libnoiseprotocol.a") L160 + include_directories("/usr/local/include") Listing A.1: Include Noise-C in c-toxcore/CMakeList.txt

1https://github.com/goldroom/c-toxcore/commit/5b50c823875362d7fcae810cc65c417e41c9bdcc

86 Appendix A. Appendix

A.5.2. Building and running minitox

Library dependencies: libtoxcore CLI commands to build minitox including functions to print Tox ID, static secret key, DHT secret key and DHT public key (tested on Debian Linux): • git clone https://github.com/goldroom/minitox.git • cd minitox • git checkout -b tb_minitox_adaptions origin/tb_minitox_adaptions – This is only necessary if Tox ID, static long-term private key, DHT private key and DHT public key of the (automatically generated) Tox profile should be printed after starting minitox. Otherwise the master branch can be used. • make • ./minitox – To run minitox

A.5.3. Building and running flakynet

Download flakynet.c from https://github.com/TokTok/toktok-stack/blob/master/ tools/debug/flakynet.c • cc flakynet.c -o flakynet.so -shared -fPIC -ldl • LD_PRELOAD=./flakynet.so ./minitox – To run minitox together with flakynet to test packet loss behavior (assuming that both files are in the same directory)

87