1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//! # Clatter 🔊
//!
//! ⚠️ **Work in progress** ⚠️
//!
//! `no_std` compatible, pure Rust implementation of the [Noise framework](https://noiseprotocol.org/noise.html)
//! with support for [**Post Quantum (PQ) extensions**](https://doi.org/10.1145/3548606.3560577) as presented by
//! Yawning Angel, Benjamin Dowling, Andreas Hülsing, Peter Schwabe, and Fiona Johanna Weber.
//!
//! From user perspective, everything in this crate is built around three types:
//!
//! * [`NqHandshake`] - Classical, non-post-quantum Noise handshake
//! * [`PqHandshake`] - Post-quantum Noise handshake
//! * [`DualLayerHandshake`] - Dual layer handshake, which combined two Noise handshakes
//!
//! Users will pick and instantiate the desired handshake state machine with the crypto primitives
//! and [`handshakepattern::HandshakePattern`] they wish to use and complete the handshake using the
//! methods provided by the common [`Handshaker`] trait:
//!
//! * [`Handshaker::write_message`] - Write next handshake message
//! * [`Handshaker::read_message`] - Read next handshake message
//! * [`Handshaker::is_finished`] - Is the handshake ready?
//! * [`Handshaker::finalize`] - Move to transport state
//!
//! Handshake messages are exchanged by the peers until the handshake is completed.
//! After completion, [`Handshaker::finalize`] is called and the handshake state machine
//! is consumed into a [`transportstate::TransportState`] instance, which can be used
//! to decrypt and encrypt communication between the peers.
//!
//! ## Crypto Vendors
//!
//! Currently Clatter has frozen the vendor selection for DH, Cipher and Hash algorithms, but users
//! can select from multiple KEM vendors.
//!
//! Concrete implementations of the crypto algorithms are in the [`crypto`] module and users can even
//! use their own implementations using the definitions in the [`traits`] module.
//!
//! ## Features
//!
//! To improve build times and produce more optimized binaries, Clatter can be heavily configured by
//! enabling and disabling crate features. Below is a listing of the available features:
//!
//! | Feature flag | Description | Default | Details |
//! | --- | --- | --- | --- |
//! | `use-25519` | Enable X25519 DH | yes | |
//! | `use-aes-gcm` | Enable AES-GCM cipher | yes | |
//! | `use-chacha20poly1305` | Enable ChaCha20-Poly1305 cipher | yes | |
//! | `use-sha` | Enable SHA-256 and SHA-512 hashing | yes | |
//! | `use-blake2` | Enable BLAKE2 hashing | yes | |
//! | `use-rust-crypto-kyber` | Enable Kyber KEMs by RustCrypto | yes | |
//! | `use-argyle-kyber512` | Eable Kyber512 KEM by Argyle-Software | no | |
//! | `use-argyle-kyber768` | Eable Kyber768 KEM by Argyle-Software | no | |
//! | `use-argyle-kyber1024` | Eable Kyber1024 KEM by Argyle-Software | no | |
//! | `std` | Enable standard library support | no | Currently only affects dependencies |
//! | `alloc` | Enable allocator support | no | Reserved for future use |
//!
//! ## Example
//!
//! Simplified example with the most straightforward (and unsecure) PQ handshake pattern and
//! no handshake payload data at all:
//!
//! ```ignore
//! use clatter::crypto::cipher::ChaChaPoly;
//! use clatter::crypto::hash::Sha512;
//! use clatter::crypto::kem::rust_crypto_kyber::Kyber512;
//! use clatter::handshakepattern::noise_pqnn;
//! use clatter::traits::Handshaker;
//! use clatter::PqHandshake;
//!
//! fn main() {
//! let mut rng_alice = rand::thread_rng();
//!
//! // Instantiate initiator handshake
//! let mut alice = PqHandshake::<Kyber512, Kyber512, ChaChaPoly, Sha512, _>::new(
//! noise_pqnn(), // Handshake pattern
//! &[], // Prologue data
//! true, // Are we the initiator
//! None, // Pre-shared keys..
//! None, // ..
//! None, // ..
//! None, // ..
//! &mut rng_alice, // RNG instance
//! ).unwrap();
//!
//! let mut buf_alice_send = [0u8; 4096];
//! let mut buf_alice_receive = [0u8; 4096];
//!
//! // Write handshake message and deliver to peer
//! let n = alice.write_message(&[], &mut buf_alice_send).unwrap();
//! my_send_function(&buf_alice_send[..n]);
//!
//! // Receive handshake message and process it
//! let n = my_receive_function(&mut buf_alice_receive);
//! let _ = alice.read_message(&buf_alice_receive[..n], &mut[]).unwrap();
//!
//! assert!(alice.is_finished());
//!
//! // Move to transport state
//! let mut alice = alice.finalize().unwrap();
//!
//! // All done! Use .send() and .receive() on the transport state to communicate
//! // with the peer
//! let n = alice.send(b"Hello from Alice", &mut buf_alice_send).unwrap();
//! my_send_function(& buf_alice_send[..n]);
//! }
//! ```
// Not really used for now
extern crate alloc;
pub use DualLayerHandshake;
pub use NqHandshake;
pub use PqHandshake;
pub use Handshaker;
use ;
// Argyle Kyber is implemented in a way that it can only provide one of these variants
compile_error!;
/// Concrete crypto implementations
/// A zeroize-on-drop container for keys