From 5463c70aaf6d3fa482608a95c6a5f725f8e2d4fa Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 6 Mar 2020 12:18:20 -0800 Subject: [PATCH] Minor stuff, and some docs --- doc/AES-GMAC-SIV.png | Bin 0 -> 48283 bytes doc/SECURITY.md | 134 +++++++++++++++++++++++++++++++++++++++++++ node/Identity.cpp | 3 +- node/Protocol.hpp | 5 ++ 4 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 doc/AES-GMAC-SIV.png create mode 100644 doc/SECURITY.md diff --git a/doc/AES-GMAC-SIV.png b/doc/AES-GMAC-SIV.png new file mode 100644 index 0000000000000000000000000000000000000000..1099653a78caf87651058e93c3119ba8abea8771 GIT binary patch literal 48283 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 z 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 AV*mgE literal 0 HcmV?d00001 diff --git a/doc/SECURITY.md b/doc/SECURITY.md new file mode 100644 index 000000000..cfa6a9965 --- /dev/null +++ b/doc/SECURITY.md @@ -0,0 +1,134 @@ +ZeroTier security and cryptographic design +======= + +(c)2020 ZeroTier, Inc. +Author(s): Adam Ierymenko + +# Introduction + +This document briefly describes the core components of ZeroTier's cryptographic and security architecture. It focuses primarily on version 2.0, ignoring deprecated v1.x constructions that are in the process of being phased out. + +The intended audience for this document is developers, auditors, and security professionals wishing to understand ZeroTier's design from a security posture point of view. It's also written to serve as the basis for professional security audits of the ZeroTier protocol and code base. + +## High-Level Protocol Design + +ZeroTier's protocol is split into two conceptual layers that we term **VL1** and **VL2**. VL1 stands for *virtual layer 1* and is a cryptographically addressed secure global peer-to-peer network responsible for moving packets between ZeroTier nodes. VL2 stands for *virtual layer 2* and is a full Ethernet emulation layer incorporating cryptographic certificate and token based access control. It's conceptually separate from VL1 but for the sake of simplicity and user experience leverages VL1's cryptographic keys and identifiers to implement this access control scheme. + +## Asymmetric Cryptography, Identities, and Addressing + +VL1 peers are cryptographically addressed. This means that their public keys constitute their addresses. Cryptographic addressing is extremely convenient in peer-to-peer networks as it makes the authentication of addresses implicit via authenticated encryption and/or cryptographic signatures. + +A ZeroTier identity consists of one or more cryptographic public keys and a short address derived from a hash of those keys. A fingerprint is simply the SHA-384 hash of these keys and is longer than an address but also shorter than the keys themselves and size-invariant across different identity types. + +#### Identity Types and Corresponding Algorithms + +* Type 0: one Curve25519 key for elliptic curve Diffie-Hellman and one Ed25519 key for Ed25519 signatures, with the address computed from a hash of both. +* Type 1: Curve25519, Ed25519, and NIST P-384 public keys, with the latter being used for signatures (the Ed25519 key is still there but is presently unused) and with *both* keys being used for elliptic curve Diffie-Hellman key agreement. In key agreement the resulting raw secret keys are hashed together using SHA-384 to combine them and yield a single session key. + +(Session keys resulting from identity key exchange and agreement are long-lived session keys. A different mechanism is used for ephemeral key negotiation.) + +#### Short Addresses + +In simple cryptographic addressing, keys are used directly as addresses throughout the system. Unfortunately even public key cryptosystems with short keys like Curve25519 still result in string representations that are prohibitively long for human beings to type. ZeroTier mitigates this usability problem by using a short hash of the public key termed a **ZeroTier address** to refer to a peer's full identity. This short address is also used at the wire level to reduce the size of the packet header. Peers may request full identities based on addresses from one another or (more often) from root servers. + +ZeroTier addresses are very short: only 40 bits or 10 hexadecimal digits, e.g. `89e92ceee5.` This makes them convenient to type but would in a naive implementation introduce a significant risk that an attacker could create a duplicate identity with a different key pair but the same address. With 40 bits an intentional collision would require only an average of about 549,755,813,888 attempts (for a 50% chance of colliding). If an attempt requires 0.5ms of CPU time on a typical contemporary desktop or server CPU, this would require about 3,000 CPU-days. Since this type of search is easy to parallelize, it would take only a few days for someone with access to a few thousand CPU cores. + +To increase the security margin of this construction an intentionally slow one-way "hashcash" or "proof of work" function is required during identity generation. This work function is slow to compute but fast to verify. In our system the cost of identity generation is increased to approximately one second per identity key pair per CPU core for a typical desktop or server CPU (e.g. an Intel Core i7 or AMD Ryzen at 2.4ghz). At this rate a search would require about 6.3 million CPU-days for a 50% probability of collision. + +While too costly for the vast majority of attackers, this cost may not be prohibitive to a nation-state level attacker or to a criminal with significant funds and/or access to a very large "botnet." It's also possible that FPGA, GPU, or ASIC acceleration could be leveraged to decrease this time in a manner similar to what's been accomplished in the area of cryptocurrency mining. + + + +## VL1 Wire Protocol + +ZeroTier's wire protocol is packet based with packets having the following basic format: + +``` +[0:8] 64-bit packet ID and cryptographic nonce +[8:13] 40-bit destination ZeroTier address +[13:18] 40-bit source ZeroTier address +[18:19] 8-bit cleartext flags, cipher, and hop count (bits: FFCCCHHH) +[19:27] 64-bit message authentication code (MAC) +-- BEGIN ENCRYPTED SECTION -- +[27:28] 8-bit inner flags and 5-bit protocol verb (bits: FFFVVVVV) +[28:...] Verb-specific packet payload +``` + +All fields (both those that remain cleartext and those that are encrypted) in a packet are authenticated except for the last three "hops" bits of the combined flags/cipher/hops field. These are masked to zero during MAC computation and verification. This is because the hops field is the only field that can be modified by third party peers in transit. It's incremented whenever a packet is forwarded by a root server or connectivity-assisting peer and is checked against a limit to prevent infinite forwarding loops. + +Packets can be up to 16,384 bytes in size. Since the most common transport is UDP and this transport does not reliably support fragmentation, ZeroTier implements its own packet fragmentation and re-assembly scheme using fragments with the following wire format: + +``` +[0:8] 64-bit packet ID of packet of which this is a fragment +[8:13] 40-bit destination ZeroTier address +[13:14] 0xff here indicates a fragment since addresses cannot start with this byte +[14:15] 4-bit total fragments and 4-bit fragment number (bits: TTTTNNNN) +[15:16] 5 reserved bits, 3-bit hop count (bits: rrrrrHHH) +[16:...] Fragment data +``` + +A fragmented packet is indicated by the presence of the flag 0x40 in its cleartext flags field. If this flag is present the receiver must expect the receipt of one or more fragments in addition to the packet's header and first fragment. The total number of fragments expected is not contained in the header but will be contained within each subsequent fragment. If a fragment is received prior to its head, it's held in the event that its head arrives as the protocol does support out of order receipt of fragments. + +Fragmentation can be effectively ignored from a security point of view (with the exception of denial of service concerns, which are mitigated by way of limits and heuristics in the code) since packet message authentication codes are checked at the packet level. Any improperly fragmented packet will fail cryptographic MAC check and be discarded. + +*Legacy: In v1.x the packet ID and nonce field was assigned from a counter maintained to avoid duplicate nonce assignment and the MAC field was the first 64 bits of a Poly1305 MAC of the packet. The overall construction was identical in form to the NaCl Salsa20/Poly1305 "secret box" construction in which the first 32 bytes of Salsa20 output are used as a one-time Poly1305 key for each packet.* + +In v2.x the packet ID and MAC field are in reality a single split 128-bit encrypted nonce and MAC field. See AES-GMAC-SIV below for this construction. + +## Symmetric Encryption: AES-GMAC-SIV + +**This is a draft and may change based on peer review and feedback.** + +In v1.x there is a risk of nonce re-use due in part to the small size of the MAC and in part to the way ZeroTier is used. More specifically the risk arises when ZeroTier VMs are cloned or ZeroTier is used on small devices that have the potential to lack both accurate timekeeping and native strong random sources. + +Salsa20 was used in v1.x since at the time the protocol was initially designed AES acceleration was not available on most mobile phones, embedded chips, and small ARM processors such as those use on Raspberry Pi and similar devices. This is no longer the case. + +For v2.x our design has three objectives: + +- Make use of FIPS140-compliant cryptographic primitives that would be available in a FIPS140-ceritified library (e.g. a FIPS build of crypto++ or openssl libcrypto), and use them in a way that could pass FIPS/NIST/NSA review. +- Use AES with hardware acceleration for extremely high performance processors with AES hardware acceleration, which is most non-trivial CPUs today. +- Incorporate some form of nonce-reuse-resistance to reduce the risk of duplicate nonces when virtual machines are cloned or on small devices, and to mitigate the short MAC. + +The proposed AES-GMAC-SIV construction attempts to achieve all these objectives by using GMAC combined with AES-CTR (both FIPS140 primitives) in a way that achieves the security bounds and characteristics of AES-GCM-SIV but could be certified as FIPS compliant. The design is almost identical to another proposed mode called AES-GCM-SIV except that GMAC is used "as-is" for FIPS-certifiability reasons. + +#### AES-GMAC-SIV Session Setup + +For each new session key, derive two sub-keys **K0** and **K1** using a key derivation function such as KBKDF-HMAC-SHA384. + +#### AES-GMAC-SIV Encryption + + + +As with all other SIV (synthetic IV) modes of operation, encryption requires two passes. Since messages are small in our system it's very likely that the second pass would be operating on data already in CPU L0 cache, reducing the additional overhead of this two-pass requirement. + +1. Generate a new unique 64-bit packet ID in the same manner as v1.x. +2. Expand this 64-bit ID to a 96-bit AES-GMAC nonce by padding the remainder with the size of the packet in bytes and the direction of communication (sender > recipient or recipient > sender). This adds a small amount of additional entropy taken from characteristics of the packet. +3. Using session sub-key **K0** compute AES-GMAC(K0, plaintext) to yield a 128-bit GMAC tag. +4. Take the first 64 bits of this 128-bit GMAC tag and append it to the 64-bit packet ID generated in step 1 to yield a 128-bit combined nonce+MAC field. +5. Obtain a 128-bit AES-CTR nonce by encrypting this 128-bit combined nonce+MAC field as a single AES block using **K1**. This is done because GMAC alone is not a cryptographic PRF (pseudo-random function) and we want to ensure that we destroy any algebraic structure before using it with AES-CTR. +6. Using the encrypted nonce+MAC field as a 128-bit nonce, encrypt the encrypted section of the packet with AES-CTR. This is also done using **K1**, meaning that the first block of CTR padding data is actually AES(K1,AES(K1,nonce+MAC)). +7. Encrypt the 128-bit AES-CTR nonce again as a single AES block using **K0** to yield a final encrypted 128-bit combined nonce and MAC. *(Question for peer review: does this step have any attack-mitigating value? AES-CTR does not require that its nonce/IV be a secret.)* +8. Split this final encrypted nonce+IV into two 64-bit chunks, replacing the packet ID with one and placing the other in the packet MAC field. + +#### AES-GMAC-SIV Decryption + +Unlike encryption, SIV decryption can be performed in a single pass if there is a performance benefit to doing so. + +1. Re-combine the packet ID and MAC fields into a single 128-bit block. +2. Decrypt this block with AES using **K0** to yield the AES-CTR nonce. +3. Decrypt the packet using AES-CTR with **K1**. +4. Decrypt the 128-bit AES-CTR nonce field *again* as a single AES block using **K1** to obtain the original packet nonce and 64-bit truncated GMAC tag. +5. Expand the 64-bit packet ID / nonce into a 96-bit GMAC nonce as in encryption step 2. +6. Compute AES-GMAC(K0,plaintext) as in encryption step 3. +7. Verify that the first 64 bytes of the resulting GMAC tag equals the tag (last 64 bits) obtained in decryption step 4 and discard the packet if they do not match. + +#### Discussion + +Most standard stream cipher modes such as AES-GCM or Salsa20/Poly1305 require that message nonce/IV values are never duplicated for the same session key. Since these stream modes generate key streams that are simply XORed with message plaintext, nonce duplication reveals the plaintext of both messages for which the nonce is duplicated due to the commutativity of the XOR operation. It may also allow the MAC (GMAC or Poly1305) itself to be attacked in such a way as to enable message forgery. + +SIV modes mitigate these attacks by making the actual cryptographic nonce used for stream encryption dependent on the content of the message. If a nonce is repeated when two messages differ, ciphertext will still be unique unless a MAC collision also occurs. The chance of this is quite small, only 1/2^64 in our system for any given pair of repeated nonce values. If a repeated nonce occurs and both messages are the same, the protocol will leak only the fact that a message was repeated. The actual plaintext and MAC are not compromised. + +Our AES-GMAC-SIV mode is almost identical to a proposed mode called [AES-GCM-SIV](https://cyber.biu.ac.il/aes-gcm-siv/). The proposed AES-GCM-SIV mode uses a variant of GMAC called POLYVAL with very minor performance improvements while ours retains standard GMAC for compatibility with existing standards and libraries. We call our mode AES-GMAC-SIV to distinguish it. + +*Question for peer review: both GMAC and AES-CTR are FIPS140 approved primitives, and the use of AES-CTR with an approved MAC is permitted. Is it actually feasible that this could be FIPS certified if it were documented in a correct and "strategic" way? It would be described as GMAC authenticated AES-CTR with the CTR IV being constructed via keyed hash (AES) from an initial plaintext IV and a "salt" taken from the MAC, or some similar description.* + diff --git a/node/Identity.cpp b/node/Identity.cpp index 103cd4ff4..f4b535de2 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -22,7 +22,8 @@ #include #include -#define ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE 400000 +// This takes around one second on a typical ~2.4ghz x64 machine. +#define ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE 1000000 namespace ZeroTier { diff --git a/node/Protocol.hpp b/node/Protocol.hpp index 46eb75fd2..1f24c95fa 100644 --- a/node/Protocol.hpp +++ b/node/Protocol.hpp @@ -237,6 +237,11 @@ */ #define ZT_PROTO_KDF_KEY_LABEL_HELLO_HMAC 'H' +/** + * HELLO exchange meta-data: random 128-bit identifier for each running instance + */ +#define ZT_PROTO_HELLO_NODE_META_INSTANCE_ID "i" + /** * HELLO exchange meta-data: signed locator for this node */