Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/libp2p/connection/noise.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2023  Pierre Krieger
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
//! Noise protocol libp2p layer.
19
//!
20
//! The [noise protocol](https://noiseprotocol.org/) is a standard framework for building
21
//! cryptographic protocols. Libp2p uses the noise protocol to provide an encryption layer on
22
//! top of which data is exchanged.
23
//!
24
//! # Protocol details
25
//!
26
//! Libp2p uses [the XX pattern](https://noiseexplorer.com/patterns/XX/). The handshake consists
27
//! of three packets:
28
//!
29
//! - The initiator generates an ephemeral key pair and sends the public key to the responder.
30
//! - The responder generates its own ephemeral key pair and sends the public key to the
31
//! initiator. Afterwards, the responder derives a shared secret and uses it to encrypt all
32
//! further communications. Now encrypted, the responder also sends back its static noise public
33
//! key (represented with the [`NoiseKey`] type of this module), its libp2p public key, and a
34
//! signature of the static noise public key made using its libp2p private key.
35
//! - The initiator, after having received the ephemeral key from the remote, derives the same
36
//! shared secret. It sends its own static noise public key, libp2p public key, and signature.
37
//!
38
//! After these three packets, the initiator and responder derive another shared secret using
39
//! both the static and ephemeral keys, which is then used to encrypt communications. Note that
40
//! the libp2p key isn't used in the key derivation.
41
//!
42
//! # Usage
43
//!
44
//! While this is out of scope of this module, the noise protocol must typically first be
45
//! negotiated using the *multistream-select* protocol. The name of the protocol is given by
46
//! the [`PROTOCOL_NAME`] constant.
47
//!
48
//! In order to use noise on top of a connection which has agreed to use noise, create a
49
//! [`HandshakeInProgress`], passing a [`NoiseKey`]. This [`NoiseKey`] is typically generated at
50
//! startup and doesn't need to be persisted after a restart.
51
//!
52
//! Use [`HandshakeInProgress::read_write`] when data is received from the wire or when the remote
53
//! is ready to receive more data. At every call, a [`NoiseHandshake`] is returned, potentially
54
//! indicating the end of the handshake.
55
//!
56
//! If the handshake is finished, a [`NoiseHandshake::Success`] is returned, containing the
57
//! [`PeerId`] of the remote, which is known to be legitimate, and a [`Noise`] object through
58
//! which all further communications should go through.
59
//!
60
61
// # Q&A
62
//
63
// ## Why not use a library such as `snow`?
64
//
65
// Snow suffers from a variety of problems:
66
//
67
// - It doesn't support `no_std`.
68
// - It uses outdated versions of dependencies.
69
// - It doesn't allow writing a single Noise message onto two consecutive buffers.
70
// - It doesn't support encoding a Noise message already present in the output buffer.
71
// - It isn't really maintained.
72
// - It doesn't give control over its random number generator.
73
//
74
75
use crate::{
76
    libp2p::{
77
        peer_id::{PeerId, PublicKey, SignatureVerifyFailed},
78
        read_write::{self, ReadWrite},
79
    },
80
    util::protobuf,
81
};
82
83
use alloc::{boxed::Box, collections::VecDeque, vec, vec::Vec};
84
use core::{cmp, fmt, iter, mem, ops};
85
86
/// Name of the protocol, typically used when negotiated it using *multistream-select*.
87
pub const PROTOCOL_NAME: &str = "/noise";
88
89
/// The noise key is the key exchanged during the noise handshake. It is **not** the same as the
90
/// libp2p key. The libp2p key is used only to sign the noise public key, while the ECDH is
91
/// performed with the noise key.
92
///
93
/// From the point of view of the noise protocol specification, this [`NoiseKey`] corresponds to
94
/// the static key. The noise key is typically generated at startup and doesn't have to be
95
/// persisted on disk, contrary to the libp2p key which is typically persisted after a restart.
96
///
97
/// In order to generate a [`NoiseKey`], two things are needed:
98
///
99
/// - A public/private key, also represented as [`UnsignedNoiseKey`].
100
/// - A signature of this public key made using the libp2p private key.
101
///
102
/// The signature requires access to the libp2p private key. As such, there are two possible
103
/// ways to create a [`NoiseKey`]:
104
///
105
/// - The easier way, by passing the libp2p private key to [`NoiseKey::new`].
106
/// - The slightly more complex way, by first creating an [`UnsignedNoiseKey`], then passing a
107
/// a signature. This second method doesn't require direct access to the private key but only
108
/// to a method of signing a message, which makes it for example possible to use a hardware
109
/// device.
110
///
111
pub struct NoiseKey {
112
    private_key: zeroize::Zeroizing<x25519_dalek::StaticSecret>,
113
    public_key: x25519_dalek::PublicKey,
114
    /// Handshake to encrypt then send on the wire.
115
    handshake_message: Vec<u8>,
116
    /// Ed25519 public key used for the signature in the handshake message.
117
    libp2p_public_ed25519_key: [u8; 32],
118
}
119
120
impl NoiseKey {
121
    /// Turns a libp2p private key and a Noise static private key into a [`NoiseKey`].
122
45
    pub fn new(libp2p_ed25519_private_key: &[u8; 32], noise_static_private_key: &[u8; 32]) -> Self {
123
45
        let unsigned = UnsignedNoiseKey::from_private_key(noise_static_private_key);
124
45
125
45
        let (libp2p_public_key, signature) = {
126
45
            // Creating a `SecretKey` can fail only if the length isn't 32 bytes.
127
45
            let secret = ed25519_zebra::SigningKey::from(*libp2p_ed25519_private_key);
128
45
            let public = ed25519_zebra::VerificationKey::from(&secret);
129
45
            // TODO: use sign_prehashed or sign_vectored (https://github.com/dalek-cryptography/ed25519-dalek/pull/143) to not allocate Vec
130
45
            let signature = secret.sign(&unsigned.payload_to_sign_as_vec());
131
45
            (public, signature)
132
45
        };
133
45
134
45
        unsigned.sign(libp2p_public_key.into(), signature.into())
135
45
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB2_8NoiseKey3new
Line
Count
Source
122
24
    pub fn new(libp2p_ed25519_private_key: &[u8; 32], noise_static_private_key: &[u8; 32]) -> Self {
123
24
        let unsigned = UnsignedNoiseKey::from_private_key(noise_static_private_key);
124
24
125
24
        let (libp2p_public_key, signature) = {
126
24
            // Creating a `SecretKey` can fail only if the length isn't 32 bytes.
127
24
            let secret = ed25519_zebra::SigningKey::from(*libp2p_ed25519_private_key);
128
24
            let public = ed25519_zebra::VerificationKey::from(&secret);
129
24
            // TODO: use sign_prehashed or sign_vectored (https://github.com/dalek-cryptography/ed25519-dalek/pull/143) to not allocate Vec
130
24
            let signature = secret.sign(&unsigned.payload_to_sign_as_vec());
131
24
            (public, signature)
132
24
        };
133
24
134
24
        unsigned.sign(libp2p_public_key.into(), signature.into())
135
24
    }
_RNvMNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB2_8NoiseKey3new
Line
Count
Source
122
21
    pub fn new(libp2p_ed25519_private_key: &[u8; 32], noise_static_private_key: &[u8; 32]) -> Self {
123
21
        let unsigned = UnsignedNoiseKey::from_private_key(noise_static_private_key);
124
21
125
21
        let (libp2p_public_key, signature) = {
126
21
            // Creating a `SecretKey` can fail only if the length isn't 32 bytes.
127
21
            let secret = ed25519_zebra::SigningKey::from(*libp2p_ed25519_private_key);
128
21
            let public = ed25519_zebra::VerificationKey::from(&secret);
129
21
            // TODO: use sign_prehashed or sign_vectored (https://github.com/dalek-cryptography/ed25519-dalek/pull/143) to not allocate Vec
130
21
            let signature = secret.sign(&unsigned.payload_to_sign_as_vec());
131
21
            (public, signature)
132
21
        };
133
21
134
21
        unsigned.sign(libp2p_public_key.into(), signature.into())
135
21
    }
136
137
    /// Returns the libp2p public key associated to the signature contained in this noise key.
138
42
    pub fn libp2p_public_ed25519_key(&self) -> &[u8; 32] {
139
42
        &self.libp2p_public_ed25519_key
140
42
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB2_8NoiseKey25libp2p_public_ed25519_key
_RNvMNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB2_8NoiseKey25libp2p_public_ed25519_key
Line
Count
Source
138
42
    pub fn libp2p_public_ed25519_key(&self) -> &[u8; 32] {
139
42
        &self.libp2p_public_ed25519_key
140
42
    }
141
}
142
143
/// Prototype for a [`NoiseKey`].
144
///
145
/// This type is provided for situations where the user has access to some signing mechanism,
146
/// such as a hardware device, but not directly to the private key.
147
///
148
/// For simple cases, prefer using [`NoiseKey::new`].
149
pub struct UnsignedNoiseKey {
150
    private_key: Option<zeroize::Zeroizing<x25519_dalek::StaticSecret>>,
151
    public_key: x25519_dalek::PublicKey,
152
}
153
154
impl UnsignedNoiseKey {
155
    /// Turns a private key into an [`UnsignedNoiseKey`].
156
45
    pub fn from_private_key(private_key: &[u8; 32]) -> Self {
157
45
        let private_key = zeroize::Zeroizing::new(x25519_dalek::StaticSecret::from(*private_key));
158
45
        let public_key = x25519_dalek::PublicKey::from(&*private_key);
159
45
        UnsignedNoiseKey {
160
45
            private_key: Some(private_key),
161
45
            public_key,
162
45
        }
163
45
    }
_RNvMs_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB4_16UnsignedNoiseKey16from_private_key
Line
Count
Source
156
24
    pub fn from_private_key(private_key: &[u8; 32]) -> Self {
157
24
        let private_key = zeroize::Zeroizing::new(x25519_dalek::StaticSecret::from(*private_key));
158
24
        let public_key = x25519_dalek::PublicKey::from(&*private_key);
159
24
        UnsignedNoiseKey {
160
24
            private_key: Some(private_key),
161
24
            public_key,
162
24
        }
163
24
    }
_RNvMs_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB4_16UnsignedNoiseKey16from_private_key
Line
Count
Source
156
21
    pub fn from_private_key(private_key: &[u8; 32]) -> Self {
157
21
        let private_key = zeroize::Zeroizing::new(x25519_dalek::StaticSecret::from(*private_key));
158
21
        let public_key = x25519_dalek::PublicKey::from(&*private_key);
159
21
        UnsignedNoiseKey {
160
21
            private_key: Some(private_key),
161
21
            public_key,
162
21
        }
163
21
    }
164
165
    /// Returns the data that has to be signed.
166
45
    pub fn payload_to_sign(&'_ self) -> impl Iterator<Item = impl AsRef<[u8]> + '_> + '_ {
167
45
        [
168
45
            &b"noise-libp2p-static-key:"[..],
169
45
            &self.public_key.as_bytes()[..],
170
45
        ]
171
45
        .into_iter()
172
45
    }
_RNvMs_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB4_16UnsignedNoiseKey15payload_to_sign
Line
Count
Source
166
24
    pub fn payload_to_sign(&'_ self) -> impl Iterator<Item = impl AsRef<[u8]> + '_> + '_ {
167
24
        [
168
24
            &b"noise-libp2p-static-key:"[..],
169
24
            &self.public_key.as_bytes()[..],
170
24
        ]
171
24
        .into_iter()
172
24
    }
_RNvMs_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB4_16UnsignedNoiseKey15payload_to_sign
Line
Count
Source
166
21
    pub fn payload_to_sign(&'_ self) -> impl Iterator<Item = impl AsRef<[u8]> + '_> + '_ {
167
21
        [
168
21
            &b"noise-libp2p-static-key:"[..],
169
21
            &self.public_key.as_bytes()[..],
170
21
        ]
171
21
        .into_iter()
172
21
    }
173
174
    /// Returns the data that has to be signed.
175
    ///
176
    /// This method is a more convenient equivalent to
177
    /// [`UnsignedNoiseKey::payload_to_sign_as_vec`].
178
45
    pub fn payload_to_sign_as_vec(&self) -> Vec<u8> {
179
90
        self.payload_to_sign().fold(Vec::new(), |mut a, b| {
180
90
            a.extend_from_slice(b.as_ref());
181
90
            a
182
90
        })
_RNCNvMs_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB6_16UnsignedNoiseKey22payload_to_sign_as_vec0Bc_
Line
Count
Source
179
48
        self.payload_to_sign().fold(Vec::new(), |mut a, b| {
180
48
            a.extend_from_slice(b.as_ref());
181
48
            a
182
48
        })
_RNCNvMs_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_16UnsignedNoiseKey22payload_to_sign_as_vec0Bc_
Line
Count
Source
179
42
        self.payload_to_sign().fold(Vec::new(), |mut a, b| {
180
42
            a.extend_from_slice(b.as_ref());
181
42
            a
182
42
        })
183
45
    }
_RNvMs_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB4_16UnsignedNoiseKey22payload_to_sign_as_vec
Line
Count
Source
178
24
    pub fn payload_to_sign_as_vec(&self) -> Vec<u8> {
179
24
        self.payload_to_sign().fold(Vec::new(), |mut a, b| {
180
            a.extend_from_slice(b.as_ref());
181
            a
182
24
        })
183
24
    }
_RNvMs_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB4_16UnsignedNoiseKey22payload_to_sign_as_vec
Line
Count
Source
178
21
    pub fn payload_to_sign_as_vec(&self) -> Vec<u8> {
179
21
        self.payload_to_sign().fold(Vec::new(), |mut a, b| {
180
            a.extend_from_slice(b.as_ref());
181
            a
182
21
        })
183
21
    }
184
185
    /// Turns this [`UnsignedNoiseKey`] into a [`NoiseKey`] after signing it using the libp2p
186
    /// private key.
187
45
    pub fn sign(mut self, libp2p_public_ed25519_key: [u8; 32], signature: [u8; 64]) -> NoiseKey {
188
45
        let libp2p_pubkey_protobuf =
189
45
            PublicKey::Ed25519(libp2p_public_ed25519_key).to_protobuf_encoding();
190
191
45
        let handshake_message = {
192
            // Protobuf message format can be found here:
193
            // https://github.com/libp2p/specs/tree/master/noise#the-libp2p-handshake-payload
194
195
            // The capacity is arbitrary but large enough to avoid Vec reallocations.
196
45
            let mut msg = Vec::with_capacity(32 + libp2p_pubkey_protobuf.len() + signature.len());
197
198
135
            for slice in protobuf::bytes_tag_encode(1, 
&libp2p_pubkey_protobuf45
) {
199
135
                msg.extend_from_slice(slice.as_ref());
200
135
            }
201
202
135
            for slice in protobuf::bytes_tag_encode(2, 
&signature45
) {
203
135
                msg.extend_from_slice(slice.as_ref());
204
135
            }
205
206
45
            msg
207
45
        };
208
45
209
45
        NoiseKey {
210
45
            public_key: self.public_key,
211
45
            private_key: self.private_key.take().unwrap(),
212
45
            libp2p_public_ed25519_key,
213
45
            handshake_message,
214
45
        }
215
45
    }
_RNvMs_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB4_16UnsignedNoiseKey4sign
Line
Count
Source
187
24
    pub fn sign(mut self, libp2p_public_ed25519_key: [u8; 32], signature: [u8; 64]) -> NoiseKey {
188
24
        let libp2p_pubkey_protobuf =
189
24
            PublicKey::Ed25519(libp2p_public_ed25519_key).to_protobuf_encoding();
190
191
24
        let handshake_message = {
192
            // Protobuf message format can be found here:
193
            // https://github.com/libp2p/specs/tree/master/noise#the-libp2p-handshake-payload
194
195
            // The capacity is arbitrary but large enough to avoid Vec reallocations.
196
24
            let mut msg = Vec::with_capacity(32 + libp2p_pubkey_protobuf.len() + signature.len());
197
198
72
            for slice in protobuf::bytes_tag_encode(1, 
&libp2p_pubkey_protobuf24
) {
199
72
                msg.extend_from_slice(slice.as_ref());
200
72
            }
201
202
72
            for slice in protobuf::bytes_tag_encode(2, 
&signature24
) {
203
72
                msg.extend_from_slice(slice.as_ref());
204
72
            }
205
206
24
            msg
207
24
        };
208
24
209
24
        NoiseKey {
210
24
            public_key: self.public_key,
211
24
            private_key: self.private_key.take().unwrap(),
212
24
            libp2p_public_ed25519_key,
213
24
            handshake_message,
214
24
        }
215
24
    }
_RNvMs_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB4_16UnsignedNoiseKey4sign
Line
Count
Source
187
21
    pub fn sign(mut self, libp2p_public_ed25519_key: [u8; 32], signature: [u8; 64]) -> NoiseKey {
188
21
        let libp2p_pubkey_protobuf =
189
21
            PublicKey::Ed25519(libp2p_public_ed25519_key).to_protobuf_encoding();
190
191
21
        let handshake_message = {
192
            // Protobuf message format can be found here:
193
            // https://github.com/libp2p/specs/tree/master/noise#the-libp2p-handshake-payload
194
195
            // The capacity is arbitrary but large enough to avoid Vec reallocations.
196
21
            let mut msg = Vec::with_capacity(32 + libp2p_pubkey_protobuf.len() + signature.len());
197
198
63
            for slice in protobuf::bytes_tag_encode(1, 
&libp2p_pubkey_protobuf21
) {
199
63
                msg.extend_from_slice(slice.as_ref());
200
63
            }
201
202
63
            for slice in protobuf::bytes_tag_encode(2, 
&signature21
) {
203
63
                msg.extend_from_slice(slice.as_ref());
204
63
            }
205
206
21
            msg
207
21
        };
208
21
209
21
        NoiseKey {
210
21
            public_key: self.public_key,
211
21
            private_key: self.private_key.take().unwrap(),
212
21
            libp2p_public_ed25519_key,
213
21
            handshake_message,
214
21
        }
215
21
    }
216
}
217
218
/// Configuration for a Noise handshake.
219
pub struct Config<'a> {
220
    /// Key to use during the handshake.
221
    pub key: &'a NoiseKey,
222
223
    /// Secret key to use for that specific handshake. Must be randomly generated. Must never be
224
    /// re-used between multiple handshakes.
225
    pub ephemeral_secret_key: &'a [u8; 32],
226
227
    /// `true` if this side of the connection must initiate the Noise handshake. `false` if it's
228
    /// the remote.
229
    pub is_initiator: bool,
230
231
    /// Prologue data. The prologue data must be identical on both sides of the handshake,
232
    /// otherwise it will fail.
233
    ///
234
    /// See <https://noiseprotocol.org/noise.html#prologue>.
235
    ///
236
    /// > **Note**: If a certain protocol specification doesn't mention any prologue, it probably
237
    /// >           means that this prologue is empty.
238
    pub prologue: &'a [u8],
239
}
240
241
/// State of the noise encryption/decryption cipher.
242
pub struct Noise {
243
    /// See [`Config::is_initiator`].
244
    is_initiator: bool,
245
246
    /// Cipher used to encrypt outgoing data.
247
    out_cipher_state: CipherState,
248
249
    /// Cipher used to decrypt incoming data.
250
    in_cipher_state: CipherState,
251
252
    /// Size in bytes of the next message to receive. `None` if unknown. If `Some`, the libp2p
253
    /// length prefix has already been stripped from the incoming stream.
254
    next_in_message_size: Option<u16>,
255
256
    /// Buffer of data containing data that has been decrypted.
257
    rx_buffer_decrypted: Vec<u8>,
258
259
    /// Value of [`ReadWrite::expected_incoming_bytes`] of the inner stream the last time that
260
    /// [`Noise::read_write`] was called. Encrypted data will be read until the length of
261
    /// [`Noise::rx_buffer_decrypted`] reaches the value in this field.
262
    inner_stream_expected_incoming_bytes: usize,
263
}
264
265
impl Noise {
266
    /// Returns the value that was provided as [`Config::is_initiator`].
267
30
    pub fn is_initiator(&self) -> bool {
268
30
        self.is_initiator
269
30
    }
_RNvMs0_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_5Noise12is_initiator
Line
Count
Source
267
30
    pub fn is_initiator(&self) -> bool {
268
30
        self.is_initiator
269
30
    }
Unexecuted instantiation: _RNvMs0_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_5Noise12is_initiator
270
271
    /// Feeds data coming from a socket and outputs data to write to the socket.
272
    ///
273
    /// Returns an object that implements `Deref<Target = ReadWrite>`. This object represents the
274
    /// decrypted stream of data.
275
    ///
276
    /// An error is returned if the protocol is being violated by the remote or if the nonce
277
    /// overflows. When that happens, the connection should be closed altogether.
278
429
    pub fn read_write<'a, TNow: Clone>(
279
429
        &'a mut self,
280
429
        outer_read_write: &'a mut ReadWrite<TNow>,
281
429
    ) -> Result<InnerReadWrite<'a, TNow>, CipherError> {
282
        // Try to pull data from `outer_read_write` to decrypt it.
283
611
        while self.rx_buffer_decrypted.is_empty()
284
271
            || self.inner_stream_expected_incoming_bytes > self.rx_buffer_decrypted.len()
285
        {
286
            // TODO: what if EOF in the middle of a message?
287
340
            if let Some(
next_in_message_size91
) = self.next_in_message_size {
288
91
                if let Ok(Some(encrypted_message)) =
289
91
                    outer_read_write.incoming_bytes_take(usize::from(next_in_message_size))
290
                {
291
91
                    self.next_in_message_size = None;
292
91
293
91
                    // Read and decrypt the message.
294
91
                    // TODO: decipher progressively, based on the inner `expected_incoming_bytes` value
295
91
                    self.in_cipher_state.read_chachapoly_message_to_vec_append(
296
91
                        &[],
297
91
                        &encrypted_message,
298
91
                        &mut self.rx_buffer_decrypted,
299
91
                    )
?0
;
300
                } else {
301
0
                    break;
302
                }
303
91
            } else if let Ok(Some(next_frame_length)) =
304
249
                outer_read_write.incoming_bytes_take_array::<2>()
305
91
            {
306
91
                self.next_in_message_size = Some(u16::from_be_bytes(next_frame_length));
307
91
            } else {
308
158
                break;
309
            }
310
        }
311
312
        // Check ahead of time if writing out a message would panic.
313
429
        if self.out_cipher_state.nonce_has_overflowed {
314
0
            return Err(CipherError::NonceOverflow);
315
429
        }
316
429
317
429
        Ok(InnerReadWrite {
318
429
            inner_read_write: ReadWrite {
319
429
                now: outer_read_write.now.clone(),
320
429
                incoming_buffer: mem::take(&mut self.rx_buffer_decrypted),
321
429
                read_bytes: 0,
322
429
                expected_incoming_bytes: if outer_read_write.expected_incoming_bytes.is_some()
323
0
                    || !outer_read_write.incoming_buffer.is_empty()
324
                {
325
429
                    Some(self.inner_stream_expected_incoming_bytes)
326
                } else {
327
0
                    None
328
                },
329
429
                write_buffers: Vec::new(),
330
429
                write_bytes_queued: 0,
331
429
                write_bytes_queueable: outer_read_write.write_bytes_queueable.map(
332
429
                    |outer_writable| cmp::min(outer_writable.saturating_sub(16 + 2), 65535 - 16),
_RNCINvMs0_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_5Noise10read_writeNtNtCsaYZPK01V26L_4core4time8DurationE0Be_
Line
Count
Source
332
424
                    |outer_writable| cmp::min(outer_writable.saturating_sub(16 + 2), 65535 - 16),
_RNCINvMs0_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_5Noise10read_writelE0Be_
Line
Count
Source
332
5
                    |outer_writable| cmp::min(outer_writable.saturating_sub(16 + 2), 65535 - 16),
Unexecuted instantiation: _RNCINvMs0_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_5Noise10read_writeNtNtCsaYZPK01V26L_4core4time8DurationE0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCINvMs0_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_5Noise10read_writepE0Be_
Unexecuted instantiation: _RNCINvMs0_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_5Noise10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantE0CsiUjFBJteJ7x_17smoldot_full_node
333
429
                ),
334
429
                wake_up_after: outer_read_write.wake_up_after.clone(),
335
429
            },
336
429
            noise: self,
337
429
            outer_read_write,
338
        })
339
429
    }
_RINvMs0_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB6_5Noise10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEBc_
Line
Count
Source
278
424
    pub fn read_write<'a, TNow: Clone>(
279
424
        &'a mut self,
280
424
        outer_read_write: &'a mut ReadWrite<TNow>,
281
424
    ) -> Result<InnerReadWrite<'a, TNow>, CipherError> {
282
        // Try to pull data from `outer_read_write` to decrypt it.
283
600
        while self.rx_buffer_decrypted.is_empty()
284
268
            || self.inner_stream_expected_incoming_bytes > self.rx_buffer_decrypted.len()
285
        {
286
            // TODO: what if EOF in the middle of a message?
287
332
            if let Some(
next_in_message_size88
) = self.next_in_message_size {
288
88
                if let Ok(Some(encrypted_message)) =
289
88
                    outer_read_write.incoming_bytes_take(usize::from(next_in_message_size))
290
                {
291
88
                    self.next_in_message_size = None;
292
88
293
88
                    // Read and decrypt the message.
294
88
                    // TODO: decipher progressively, based on the inner `expected_incoming_bytes` value
295
88
                    self.in_cipher_state.read_chachapoly_message_to_vec_append(
296
88
                        &[],
297
88
                        &encrypted_message,
298
88
                        &mut self.rx_buffer_decrypted,
299
88
                    )
?0
;
300
                } else {
301
0
                    break;
302
                }
303
88
            } else if let Ok(Some(next_frame_length)) =
304
244
                outer_read_write.incoming_bytes_take_array::<2>()
305
88
            {
306
88
                self.next_in_message_size = Some(u16::from_be_bytes(next_frame_length));
307
88
            } else {
308
156
                break;
309
            }
310
        }
311
312
        // Check ahead of time if writing out a message would panic.
313
424
        if self.out_cipher_state.nonce_has_overflowed {
314
0
            return Err(CipherError::NonceOverflow);
315
424
        }
316
424
317
424
        Ok(InnerReadWrite {
318
424
            inner_read_write: ReadWrite {
319
424
                now: outer_read_write.now.clone(),
320
424
                incoming_buffer: mem::take(&mut self.rx_buffer_decrypted),
321
424
                read_bytes: 0,
322
424
                expected_incoming_bytes: if outer_read_write.expected_incoming_bytes.is_some()
323
0
                    || !outer_read_write.incoming_buffer.is_empty()
324
                {
325
424
                    Some(self.inner_stream_expected_incoming_bytes)
326
                } else {
327
0
                    None
328
                },
329
424
                write_buffers: Vec::new(),
330
424
                write_bytes_queued: 0,
331
424
                write_bytes_queueable: outer_read_write.write_bytes_queueable.map(
332
424
                    |outer_writable| cmp::min(outer_writable.saturating_sub(16 + 2), 65535 - 16),
333
424
                ),
334
424
                wake_up_after: outer_read_write.wake_up_after.clone(),
335
424
            },
336
424
            noise: self,
337
424
            outer_read_write,
338
        })
339
424
    }
_RINvMs0_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB6_5Noise10read_writelEBc_
Line
Count
Source
278
5
    pub fn read_write<'a, TNow: Clone>(
279
5
        &'a mut self,
280
5
        outer_read_write: &'a mut ReadWrite<TNow>,
281
5
    ) -> Result<InnerReadWrite<'a, TNow>, CipherError> {
282
        // Try to pull data from `outer_read_write` to decrypt it.
283
11
        while self.rx_buffer_decrypted.is_empty()
284
3
            || self.inner_stream_expected_incoming_bytes > self.rx_buffer_decrypted.len()
285
        {
286
            // TODO: what if EOF in the middle of a message?
287
8
            if let Some(
next_in_message_size3
) = self.next_in_message_size {
288
3
                if let Ok(Some(encrypted_message)) =
289
3
                    outer_read_write.incoming_bytes_take(usize::from(next_in_message_size))
290
                {
291
3
                    self.next_in_message_size = None;
292
3
293
3
                    // Read and decrypt the message.
294
3
                    // TODO: decipher progressively, based on the inner `expected_incoming_bytes` value
295
3
                    self.in_cipher_state.read_chachapoly_message_to_vec_append(
296
3
                        &[],
297
3
                        &encrypted_message,
298
3
                        &mut self.rx_buffer_decrypted,
299
3
                    )
?0
;
300
                } else {
301
0
                    break;
302
                }
303
3
            } else if let Ok(Some(next_frame_length)) =
304
5
                outer_read_write.incoming_bytes_take_array::<2>()
305
3
            {
306
3
                self.next_in_message_size = Some(u16::from_be_bytes(next_frame_length));
307
3
            } else {
308
2
                break;
309
            }
310
        }
311
312
        // Check ahead of time if writing out a message would panic.
313
5
        if self.out_cipher_state.nonce_has_overflowed {
314
0
            return Err(CipherError::NonceOverflow);
315
5
        }
316
5
317
5
        Ok(InnerReadWrite {
318
5
            inner_read_write: ReadWrite {
319
5
                now: outer_read_write.now.clone(),
320
5
                incoming_buffer: mem::take(&mut self.rx_buffer_decrypted),
321
5
                read_bytes: 0,
322
5
                expected_incoming_bytes: if outer_read_write.expected_incoming_bytes.is_some()
323
0
                    || !outer_read_write.incoming_buffer.is_empty()
324
                {
325
5
                    Some(self.inner_stream_expected_incoming_bytes)
326
                } else {
327
0
                    None
328
                },
329
5
                write_buffers: Vec::new(),
330
5
                write_bytes_queued: 0,
331
5
                write_bytes_queueable: outer_read_write.write_bytes_queueable.map(
332
5
                    |outer_writable| cmp::min(outer_writable.saturating_sub(16 + 2), 65535 - 16),
333
5
                ),
334
5
                wake_up_after: outer_read_write.wake_up_after.clone(),
335
5
            },
336
5
            noise: self,
337
5
            outer_read_write,
338
        })
339
5
    }
Unexecuted instantiation: _RINvMs0_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_5Noise10read_writeNtNtCsaYZPK01V26L_4core4time8DurationECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvMs0_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_5Noise10read_writepEBc_
Unexecuted instantiation: _RINvMs0_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_5Noise10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantECsiUjFBJteJ7x_17smoldot_full_node
340
}
341
342
impl fmt::Debug for Noise {
343
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
344
0
        f.debug_struct("Noise").finish()
345
0
    }
Unexecuted instantiation: _RNvXs1_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_5NoiseNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXs1_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_5NoiseNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
346
}
347
348
/// Stream of decrypted data. See [`Noise::read_write`].
349
pub struct InnerReadWrite<'a, TNow: Clone> {
350
    noise: &'a mut Noise,
351
    outer_read_write: &'a mut ReadWrite<TNow>,
352
    inner_read_write: ReadWrite<TNow>,
353
}
354
355
impl<'a, TNow: Clone> ops::Deref for InnerReadWrite<'a, TNow> {
356
    type Target = ReadWrite<TNow>;
357
358
0
    fn deref(&self) -> &Self::Target {
359
0
        &self.inner_read_write
360
0
    }
Unexecuted instantiation: _RNvXININtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noises2_0pEINtB5_14InnerReadWritepENtNtNtCsaYZPK01V26L_4core3ops5deref5Deref5derefBb_
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noises2_0pEINtB5_14InnerReadWritepENtNtNtCsaYZPK01V26L_4core3ops5deref5Deref5derefBb_
361
}
362
363
impl<'a, TNow: Clone> ops::DerefMut for InnerReadWrite<'a, TNow> {
364
429
    fn deref_mut(&mut self) -> &mut Self::Target {
365
429
        &mut self.inner_read_write
366
429
    }
_RNvXs3_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseINtB5_14InnerReadWriteNtNtCsaYZPK01V26L_4core4time8DurationENtNtNtB1l_3ops5deref8DerefMut9deref_mutBb_
Line
Count
Source
364
424
    fn deref_mut(&mut self) -> &mut Self::Target {
365
424
        &mut self.inner_read_write
366
424
    }
_RNvXs3_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseINtB5_14InnerReadWritelENtNtNtCsaYZPK01V26L_4core3ops5deref8DerefMut9deref_mutBb_
Line
Count
Source
364
5
    fn deref_mut(&mut self) -> &mut Self::Target {
365
5
        &mut self.inner_read_write
366
5
    }
Unexecuted instantiation: _RNvXs3_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseINtB5_14InnerReadWriteNtNtCsaYZPK01V26L_4core4time8DurationENtNtNtB1m_3ops5deref8DerefMut9deref_mutCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noises3_0pEINtB5_14InnerReadWritepENtNtNtCsaYZPK01V26L_4core3ops5deref8DerefMut9deref_mutBb_
Unexecuted instantiation: _RNvXs3_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseINtB5_14InnerReadWriteNtNtCsbpXXxgr6u8g_3std4time7InstantENtNtNtCsaYZPK01V26L_4core3ops5deref8DerefMut9deref_mutCsiUjFBJteJ7x_17smoldot_full_node
367
}
368
369
impl<'a, TNow: Clone> Drop for InnerReadWrite<'a, TNow> {
370
429
    fn drop(&mut self) {
371
429
        self.outer_read_write.wake_up_after = self.inner_read_write.wake_up_after.clone();
372
429
        self.noise.rx_buffer_decrypted = mem::take(&mut self.inner_read_write.incoming_buffer);
373
429
        self.noise.inner_stream_expected_incoming_bytes =
374
429
            self.inner_read_write.expected_incoming_bytes.unwrap_or(0);
375
429
376
429
        // It is possible that the inner stream processes some bytes of `self.rx_buffer_decrypted`
377
429
        // and expects to be called again while no bytes was pulled from the outer `ReadWrite`.
378
429
        // If that happens, the API user will not call `read_write` again and we will have a stall.
379
429
        // For this reason, if the inner stream has read some bytes, we make sure that the outer
380
429
        // `ReadWrite` wakes up as soon as possible.
381
429
        if self.inner_read_write.read_bytes != 0 {
382
208
            self.outer_read_write.wake_up_asap();
383
221
        }
384
385
        // Encrypt the data, transferring it from the inner `ReadWrite` to the outer `ReadWrite`.
386
429
        if self
387
429
            .inner_read_write
388
429
            .write_buffers
389
429
            .iter()
390
429
            .any(|b| 
!b.is_empty()93
)
_RNCNvXs4_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseINtB7_14InnerReadWriteNtNtCsaYZPK01V26L_4core4time8DurationENtNtNtB1n_3ops4drop4Drop4drop0Bd_
Line
Count
Source
390
90
            .any(|b| !b.is_empty())
_RNCNvXs4_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseINtB7_14InnerReadWritelENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4drop0Bd_
Line
Count
Source
390
3
            .any(|b| !b.is_empty())
Unexecuted instantiation: _RNCNvXs4_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseINtB7_14InnerReadWriteNtNtCsaYZPK01V26L_4core4time8DurationENtNtNtB1o_3ops4drop4Drop4drop0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvXININtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noises4_0pEINtB7_14InnerReadWritepENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4drop0Bd_
Unexecuted instantiation: _RNCNvXs4_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseINtB7_14InnerReadWriteNtNtCsbpXXxgr6u8g_3std4time7InstantENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4drop0CsiUjFBJteJ7x_17smoldot_full_node
391
        {
392
93
            self.outer_read_write
393
93
                .write_buffers
394
93
                .reserve(2 + self.inner_read_write.write_buffers.len() * 2);
395
93
396
93
            // We push a dummy buffer to `outer_read_write.write_buffers`. This dummy buffer
397
93
            // will later be overwritten with the actual message length.
398
93
            let message_length_prefix_index = self.outer_read_write.write_buffers.len();
399
93
            self.outer_read_write.write_buffers.push(Vec::new());
400
93
401
93
            // Encrypt the message.
402
93
            // `write_chachapoly_message` returns an error if the nonce has overflowed. It has
403
93
            // been checked in the body of `read_write` that this can't happen.
404
93
            let mut total_size = 0;
405
279
            for encrypted_buffer in self
406
93
                .noise
407
93
                .out_cipher_state
408
93
                .write_chachapoly_message(&[], self.inner_read_write.write_buffers.drain(..))
409
93
                .unwrap_or_else(|_| 
unreachable!()0
)
Unexecuted instantiation: _RNCNvXs4_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseINtB7_14InnerReadWriteNtNtCsaYZPK01V26L_4core4time8DurationENtNtNtB1n_3ops4drop4Drop4drops_0Bd_
Unexecuted instantiation: _RNCNvXs4_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseINtB7_14InnerReadWritelENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4drops_0Bd_
Unexecuted instantiation: _RNCNvXs4_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseINtB7_14InnerReadWriteNtNtCsaYZPK01V26L_4core4time8DurationENtNtNtB1o_3ops4drop4Drop4drops_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvXININtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noises4_0pEINtB7_14InnerReadWritepENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4drops_0Bd_
Unexecuted instantiation: _RNCNvXs4_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseINtB7_14InnerReadWriteNtNtCsbpXXxgr6u8g_3std4time7InstantENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4drops_0CsiUjFBJteJ7x_17smoldot_full_node
410
279
            {
411
279
                total_size += encrypted_buffer.len();
412
279
                self.outer_read_write.write_buffers.push(encrypted_buffer);
413
279
            }
414
415
            // Now write the message length.
416
93
            let message_length_prefix = u16::try_from(total_size).unwrap().to_be_bytes().to_vec();
417
93
            self.outer_read_write.write_buffers[message_length_prefix_index] =
418
93
                message_length_prefix;
419
93
420
93
            // Properly update the outer `ReadWrite`.
421
93
            self.outer_read_write.write_bytes_queued += total_size + 2;
422
93
            *self
423
93
                .outer_read_write
424
93
                .write_bytes_queueable
425
93
                .as_mut()
426
93
                .unwrap() -= total_size + 2;
427
336
        }
428
429
    }
_RNvXs4_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseINtB5_14InnerReadWriteNtNtCsaYZPK01V26L_4core4time8DurationENtNtNtB1l_3ops4drop4Drop4dropBb_
Line
Count
Source
370
424
    fn drop(&mut self) {
371
424
        self.outer_read_write.wake_up_after = self.inner_read_write.wake_up_after.clone();
372
424
        self.noise.rx_buffer_decrypted = mem::take(&mut self.inner_read_write.incoming_buffer);
373
424
        self.noise.inner_stream_expected_incoming_bytes =
374
424
            self.inner_read_write.expected_incoming_bytes.unwrap_or(0);
375
424
376
424
        // It is possible that the inner stream processes some bytes of `self.rx_buffer_decrypted`
377
424
        // and expects to be called again while no bytes was pulled from the outer `ReadWrite`.
378
424
        // If that happens, the API user will not call `read_write` again and we will have a stall.
379
424
        // For this reason, if the inner stream has read some bytes, we make sure that the outer
380
424
        // `ReadWrite` wakes up as soon as possible.
381
424
        if self.inner_read_write.read_bytes != 0 {
382
205
            self.outer_read_write.wake_up_asap();
383
219
        }
384
385
        // Encrypt the data, transferring it from the inner `ReadWrite` to the outer `ReadWrite`.
386
424
        if self
387
424
            .inner_read_write
388
424
            .write_buffers
389
424
            .iter()
390
424
            .any(|b| !b.is_empty())
391
        {
392
90
            self.outer_read_write
393
90
                .write_buffers
394
90
                .reserve(2 + self.inner_read_write.write_buffers.len() * 2);
395
90
396
90
            // We push a dummy buffer to `outer_read_write.write_buffers`. This dummy buffer
397
90
            // will later be overwritten with the actual message length.
398
90
            let message_length_prefix_index = self.outer_read_write.write_buffers.len();
399
90
            self.outer_read_write.write_buffers.push(Vec::new());
400
90
401
90
            // Encrypt the message.
402
90
            // `write_chachapoly_message` returns an error if the nonce has overflowed. It has
403
90
            // been checked in the body of `read_write` that this can't happen.
404
90
            let mut total_size = 0;
405
270
            for encrypted_buffer in self
406
90
                .noise
407
90
                .out_cipher_state
408
90
                .write_chachapoly_message(&[], self.inner_read_write.write_buffers.drain(..))
409
90
                .unwrap_or_else(|_| unreachable!())
410
270
            {
411
270
                total_size += encrypted_buffer.len();
412
270
                self.outer_read_write.write_buffers.push(encrypted_buffer);
413
270
            }
414
415
            // Now write the message length.
416
90
            let message_length_prefix = u16::try_from(total_size).unwrap().to_be_bytes().to_vec();
417
90
            self.outer_read_write.write_buffers[message_length_prefix_index] =
418
90
                message_length_prefix;
419
90
420
90
            // Properly update the outer `ReadWrite`.
421
90
            self.outer_read_write.write_bytes_queued += total_size + 2;
422
90
            *self
423
90
                .outer_read_write
424
90
                .write_bytes_queueable
425
90
                .as_mut()
426
90
                .unwrap() -= total_size + 2;
427
334
        }
428
424
    }
_RNvXs4_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseINtB5_14InnerReadWritelENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4dropBb_
Line
Count
Source
370
5
    fn drop(&mut self) {
371
5
        self.outer_read_write.wake_up_after = self.inner_read_write.wake_up_after.clone();
372
5
        self.noise.rx_buffer_decrypted = mem::take(&mut self.inner_read_write.incoming_buffer);
373
5
        self.noise.inner_stream_expected_incoming_bytes =
374
5
            self.inner_read_write.expected_incoming_bytes.unwrap_or(0);
375
5
376
5
        // It is possible that the inner stream processes some bytes of `self.rx_buffer_decrypted`
377
5
        // and expects to be called again while no bytes was pulled from the outer `ReadWrite`.
378
5
        // If that happens, the API user will not call `read_write` again and we will have a stall.
379
5
        // For this reason, if the inner stream has read some bytes, we make sure that the outer
380
5
        // `ReadWrite` wakes up as soon as possible.
381
5
        if self.inner_read_write.read_bytes != 0 {
382
3
            self.outer_read_write.wake_up_asap();
383
3
        }
2
384
385
        // Encrypt the data, transferring it from the inner `ReadWrite` to the outer `ReadWrite`.
386
5
        if self
387
5
            .inner_read_write
388
5
            .write_buffers
389
5
            .iter()
390
5
            .any(|b| !b.is_empty())
391
        {
392
3
            self.outer_read_write
393
3
                .write_buffers
394
3
                .reserve(2 + self.inner_read_write.write_buffers.len() * 2);
395
3
396
3
            // We push a dummy buffer to `outer_read_write.write_buffers`. This dummy buffer
397
3
            // will later be overwritten with the actual message length.
398
3
            let message_length_prefix_index = self.outer_read_write.write_buffers.len();
399
3
            self.outer_read_write.write_buffers.push(Vec::new());
400
3
401
3
            // Encrypt the message.
402
3
            // `write_chachapoly_message` returns an error if the nonce has overflowed. It has
403
3
            // been checked in the body of `read_write` that this can't happen.
404
3
            let mut total_size = 0;
405
9
            for encrypted_buffer in self
406
3
                .noise
407
3
                .out_cipher_state
408
3
                .write_chachapoly_message(&[], self.inner_read_write.write_buffers.drain(..))
409
3
                .unwrap_or_else(|_| unreachable!())
410
9
            {
411
9
                total_size += encrypted_buffer.len();
412
9
                self.outer_read_write.write_buffers.push(encrypted_buffer);
413
9
            }
414
415
            // Now write the message length.
416
3
            let message_length_prefix = u16::try_from(total_size).unwrap().to_be_bytes().to_vec();
417
3
            self.outer_read_write.write_buffers[message_length_prefix_index] =
418
3
                message_length_prefix;
419
3
420
3
            // Properly update the outer `ReadWrite`.
421
3
            self.outer_read_write.write_bytes_queued += total_size + 2;
422
3
            *self
423
3
                .outer_read_write
424
3
                .write_bytes_queueable
425
3
                .as_mut()
426
3
                .unwrap() -= total_size + 2;
427
2
        }
428
5
    }
Unexecuted instantiation: _RNvXs4_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseINtB5_14InnerReadWriteNtNtCsaYZPK01V26L_4core4time8DurationENtNtNtB1m_3ops4drop4Drop4dropCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noises4_0pEINtB5_14InnerReadWritepENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4dropBb_
Unexecuted instantiation: _RNvXs4_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseINtB5_14InnerReadWriteNtNtCsbpXXxgr6u8g_3std4time7InstantENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4dropCsiUjFBJteJ7x_17smoldot_full_node
429
}
430
431
/// State of a Noise handshake.
432
#[derive(Debug)]
433
pub enum NoiseHandshake {
434
    /// Handshake still in progress. More data needs to be sent or received.
435
    InProgress(HandshakeInProgress),
436
    /// Noise handshake has successfully completed.
437
    Success {
438
        /// Object to use to encrypt and decrypt all further communications.
439
        cipher: Noise,
440
        /// [`PeerId`] of the remote.
441
        remote_peer_id: PeerId,
442
    },
443
}
444
445
/// Handshake still in progress. More data needs to be sent or received.
446
pub struct HandshakeInProgress(Box<HandshakeInProgressInner>);
447
448
/// The actual fields are wrapped within a `Box` because we move the `HandshakeInProgress`
449
/// frequently.
450
struct HandshakeInProgressInner {
451
    /// See [`Config::is_initiator`].
452
    is_initiator: bool,
453
454
    /// Queued data that should be sent out as soon as possible.
455
    pending_out_data: VecDeque<u8>,
456
457
    /// Size of the next message being received, if already known.
458
    ///
459
    /// If `Some`, the libp2p size prefix has already been extracted from the incoming buffer.
460
    /// If `None`, this hasn't been done yet.
461
    next_in_message_size: Option<u16>,
462
463
    /// Progression of the handshake.
464
    ///
465
    /// Every time a message is sent out or buffered in
466
    /// [`HandshakeInProgressInner::pending_out_data`], this is increased by 1.
467
    num_buffered_or_transmitted_messages: u8,
468
469
    /// A single cipher is used during the handshake, as each side takes turn to send data rather
470
    /// than both at the same time.
471
    cipher_state: CipherState,
472
473
    /// Product of the diffie-hellmans between the various keys that are exchanged. Used to
474
    /// initialize the ciphers once the handshake is over.
475
    ///
476
    /// Corresponds to the `ck` field of the `SymmetricState` in the Noise specification.
477
    /// See <https://noiseprotocol.org/noise.html#the-symmetricstate-object>.
478
    chaining_key: zeroize::Zeroizing<[u8; 32]>,
479
480
    /// Hash that maintains the state of the data that we've sent out or received. Used as the
481
    /// associated data whenever we produce or verify a frame during the handshake.
482
    ///
483
    /// Corresponds to the `h` field of the `SymmetricState` in the Noise specification.
484
    /// See <https://noiseprotocol.org/noise.html#the-symmetricstate-object>.
485
    hash: zeroize::Zeroizing<[u8; 32]>,
486
487
    /// Local ephemeral key. Generate for this handshake specifically.
488
    ///
489
    /// Corresponds to the `e` field of the `HandshakeState` in the Noise specification.
490
    /// See <https://noiseprotocol.org/noise.html#the-handshakestate-object>.
491
    local_ephemeral_private_key: zeroize::Zeroizing<x25519_dalek::StaticSecret>,
492
493
    /// Local static key. Corresponds to a [`NoiseKey`].
494
    ///
495
    /// Corresponds to the `s` field of the `HandshakeState` in the Noise specification.
496
    /// See <https://noiseprotocol.org/noise.html#the-handshakestate-object>.
497
    local_static_private_key: zeroize::Zeroizing<x25519_dalek::StaticSecret>,
498
499
    /// Public key corresponding to [`HandshakeInProgressInner::local_static_private_key`].
500
    local_static_public_key: x25519_dalek::PublicKey,
501
502
    /// Ephemeral public key of the remote. Initially set to `0`s, then set to the correct value
503
    /// once it's been received.
504
    ///
505
    /// Corresponds to the `re` field of the `HandshakeState` in the Noise specification.
506
    /// See <https://noiseprotocol.org/noise.html#the-handshakestate-object>.
507
    remote_ephemeral_public_key: x25519_dalek::PublicKey,
508
509
    /// Static public key of the remote. Initially set to `0`s, then set to the correct value
510
    /// once it's been received.
511
    ///
512
    /// Corresponds to the `rs` field of the `HandshakeState` in the Noise specification.
513
    /// See <https://noiseprotocol.org/noise.html#the-handshakestate-object>.
514
    remote_static_public_key: x25519_dalek::PublicKey,
515
516
    /// Libp2p public key of the remote. Initially `None`, then set to the correct value once
517
    /// we've received it.
518
    remote_public_key: Option<PublicKey>,
519
520
    /// Libp2p-specific additional handshake message to encrypt then send to the remote.
521
    libp2p_handshake_message: Vec<u8>,
522
}
523
524
impl NoiseHandshake {
525
    /// Shortcut function that calls [`HandshakeInProgress::new`] and wraps it into a
526
    /// [`NoiseHandshake`].
527
8
    pub fn new(config: Config) -> Self {
528
8
        NoiseHandshake::InProgress(HandshakeInProgress::new(config))
529
8
    }
_RNvMs5_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_14NoiseHandshake3new
Line
Count
Source
527
8
    pub fn new(config: Config) -> Self {
528
8
        NoiseHandshake::InProgress(HandshakeInProgress::new(config))
529
8
    }
Unexecuted instantiation: _RNvMs5_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_14NoiseHandshake3new
530
}
531
532
impl HandshakeInProgress {
533
    /// Initializes a new noise handshake state machine.
534
24
    pub fn new(config: Config) -> Self {
535
24
        // Generate a new ephemeral key for this handshake.
536
24
        // TODO: is it zeroize-safe to call `from([u8; 32])`?
537
24
        let local_ephemeral_private_key = zeroize::Zeroizing::new(
538
24
            x25519_dalek::StaticSecret::from(*config.ephemeral_secret_key),
539
24
        );
540
24
541
24
        // Initialize the hash.
542
24
        let mut hash = zeroize::Zeroizing::new([0u8; 32]);
543
24
544
24
        // InitializeSymmetric(protocol_name).
545
24
        {
546
24
            const PROTOCOL_NAME: &[u8] = b"Noise_XX_25519_ChaChaPoly_SHA256";
547
24
            if PROTOCOL_NAME.len() <= hash.len() {
548
24
                hash[..PROTOCOL_NAME.len()].copy_from_slice(PROTOCOL_NAME);
549
24
                hash[PROTOCOL_NAME.len()..].fill(0);
550
24
            } else {
551
0
                let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
552
0
                sha2::Digest::update(&mut hasher, PROTOCOL_NAME);
553
0
                sha2::Digest::finalize_into(
554
0
                    hasher,
555
0
                    sha2::digest::generic_array::GenericArray::from_mut_slice(&mut *hash),
556
0
                );
557
0
            }
558
        }
559
24
        let chaining_key = hash.clone();
560
24
561
24
        // Perform MixHash(prologue).
562
24
        mix_hash(&mut hash, config.prologue);
563
24
564
24
        HandshakeInProgress(Box::new(HandshakeInProgressInner {
565
24
            cipher_state: CipherState {
566
24
                key: zeroize::Zeroizing::new([0; 32]),
567
24
                nonce: 0,
568
24
                nonce_has_overflowed: false,
569
24
            },
570
24
            chaining_key,
571
24
            hash,
572
24
            local_ephemeral_private_key,
573
24
            local_static_private_key: config.key.private_key.clone(),
574
24
            local_static_public_key: config.key.public_key,
575
24
            remote_ephemeral_public_key: x25519_dalek::PublicKey::from([0; 32]),
576
24
            remote_static_public_key: x25519_dalek::PublicKey::from([0; 32]),
577
24
            remote_public_key: None,
578
24
            is_initiator: config.is_initiator,
579
24
            pending_out_data: VecDeque::with_capacity(usize::from(u16::MAX) + 2),
580
24
            next_in_message_size: None,
581
24
            num_buffered_or_transmitted_messages: 0,
582
24
            libp2p_handshake_message: config.key.handshake_message.clone(),
583
24
        }))
584
24
    }
_RNvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_19HandshakeInProgress3new
Line
Count
Source
534
24
    pub fn new(config: Config) -> Self {
535
24
        // Generate a new ephemeral key for this handshake.
536
24
        // TODO: is it zeroize-safe to call `from([u8; 32])`?
537
24
        let local_ephemeral_private_key = zeroize::Zeroizing::new(
538
24
            x25519_dalek::StaticSecret::from(*config.ephemeral_secret_key),
539
24
        );
540
24
541
24
        // Initialize the hash.
542
24
        let mut hash = zeroize::Zeroizing::new([0u8; 32]);
543
24
544
24
        // InitializeSymmetric(protocol_name).
545
24
        {
546
24
            const PROTOCOL_NAME: &[u8] = b"Noise_XX_25519_ChaChaPoly_SHA256";
547
24
            if PROTOCOL_NAME.len() <= hash.len() {
548
24
                hash[..PROTOCOL_NAME.len()].copy_from_slice(PROTOCOL_NAME);
549
24
                hash[PROTOCOL_NAME.len()..].fill(0);
550
24
            } else {
551
0
                let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
552
0
                sha2::Digest::update(&mut hasher, PROTOCOL_NAME);
553
0
                sha2::Digest::finalize_into(
554
0
                    hasher,
555
0
                    sha2::digest::generic_array::GenericArray::from_mut_slice(&mut *hash),
556
0
                );
557
0
            }
558
        }
559
24
        let chaining_key = hash.clone();
560
24
561
24
        // Perform MixHash(prologue).
562
24
        mix_hash(&mut hash, config.prologue);
563
24
564
24
        HandshakeInProgress(Box::new(HandshakeInProgressInner {
565
24
            cipher_state: CipherState {
566
24
                key: zeroize::Zeroizing::new([0; 32]),
567
24
                nonce: 0,
568
24
                nonce_has_overflowed: false,
569
24
            },
570
24
            chaining_key,
571
24
            hash,
572
24
            local_ephemeral_private_key,
573
24
            local_static_private_key: config.key.private_key.clone(),
574
24
            local_static_public_key: config.key.public_key,
575
24
            remote_ephemeral_public_key: x25519_dalek::PublicKey::from([0; 32]),
576
24
            remote_static_public_key: x25519_dalek::PublicKey::from([0; 32]),
577
24
            remote_public_key: None,
578
24
            is_initiator: config.is_initiator,
579
24
            pending_out_data: VecDeque::with_capacity(usize::from(u16::MAX) + 2),
580
24
            next_in_message_size: None,
581
24
            num_buffered_or_transmitted_messages: 0,
582
24
            libp2p_handshake_message: config.key.handshake_message.clone(),
583
24
        }))
584
24
    }
Unexecuted instantiation: _RNvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_19HandshakeInProgress3new
585
586
    /// Feeds data coming from a socket and outputs data to write to the socket.
587
    ///
588
    /// On success, returns the new state of the negotiation.
589
    ///
590
    /// An error is returned if the protocol is being violated by the remote. When that happens,
591
    /// the connection should be closed altogether.
592
72
    pub fn read_write<TNow>(
593
72
        mut self,
594
72
        read_write: &mut ReadWrite<TNow>,
595
72
    ) -> Result<NoiseHandshake, HandshakeError> {
596
144
        loop {
597
144
            // Write out the data currently buffered waiting to be written out.
598
144
            // If we didn't finish writing our payload, don't do anything more and return now.
599
144
            // Don't even read the data from the remote.
600
144
            read_write.write_from_vec_deque(&mut self.0.pending_out_data);
601
144
            if !self.0.pending_out_data.is_empty() {
602
8
                if read_write.write_bytes_queueable.is_none() {
603
0
                    return Err(HandshakeError::WriteClosed);
604
8
                }
605
8
                return Ok(NoiseHandshake::InProgress(self));
606
136
            }
607
136
608
136
            // If the handshake has finished, we return successfully here.
609
136
            if self.0.num_buffered_or_transmitted_messages == 3 {
610
24
                debug_assert!(self.0.pending_out_data.is_empty());
611
24
                debug_assert!(self.0.next_in_message_size.is_none());
612
613
                // Perform the `Split()`.
614
                let HkdfOutput {
615
24
                    output1: init_to_resp,
616
24
                    output2: resp_to_init,
617
24
                } = hkdf(&self.0.chaining_key, &[]);
618
24
                let (out_key, in_key) = match self.0.is_initiator {
619
12
                    true => (init_to_resp, resp_to_init),
620
12
                    false => (resp_to_init, init_to_resp),
621
                };
622
24
                return Ok(NoiseHandshake::Success {
623
24
                    cipher: Noise {
624
24
                        is_initiator: self.0.is_initiator,
625
24
                        out_cipher_state: CipherState {
626
24
                            key: out_key,
627
24
                            nonce: 0,
628
24
                            nonce_has_overflowed: false,
629
24
                        },
630
24
                        in_cipher_state: CipherState {
631
24
                            key: in_key,
632
24
                            nonce: 0,
633
24
                            nonce_has_overflowed: false,
634
24
                        },
635
24
                        rx_buffer_decrypted: Vec::with_capacity(65535 - 16),
636
24
                        next_in_message_size: None,
637
24
                        inner_stream_expected_incoming_bytes: 0,
638
24
                    },
639
24
                    remote_peer_id: {
640
24
                        // The logic of this module guarantees that `remote_peer_id` has
641
24
                        // been set during the handshake.
642
24
                        self.0
643
24
                            .remote_public_key
644
24
                            .take()
645
24
                            .unwrap_or_else(|| 
unreachable!()0
)
Unexecuted instantiation: _RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationE0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writelE0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationE0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writepE0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantE0CsiUjFBJteJ7x_17smoldot_full_node
646
24
                            .into_peer_id()
647
24
                    },
648
24
                });
649
112
            }
650
112
651
112
            // If the handshake is in a phase where we need to send out more data, queue said
652
112
            // data to `pending_out_data` and continue.
653
112
            match (
654
112
                self.0.num_buffered_or_transmitted_messages,
655
112
                self.0.is_initiator,
656
112
            ) {
657
                (0, true) => {
658
                    // Send `e`, the ephemeral local public key.
659
660
                    // Process `e`.
661
12
                    let local_ephemeral_public_key =
662
12
                        x25519_dalek::PublicKey::from(&*self.0.local_ephemeral_private_key);
663
12
                    self.0
664
12
                        .pending_out_data
665
12
                        .extend(local_ephemeral_public_key.as_bytes());
666
12
                    mix_hash(&mut self.0.hash, local_ephemeral_public_key.as_bytes());
667
12
668
12
                    // Call MixHash(&[]) to process the empty payload.
669
12
                    mix_hash(&mut self.0.hash, &[]);
670
12
671
12
                    // Add the libp2p message length.
672
12
                    let len = u16::try_from(self.0.pending_out_data.len())
673
12
                        .unwrap()
674
12
                        .to_be_bytes();
675
12
                    self.0.pending_out_data.push_front(len[1]);
676
12
                    self.0.pending_out_data.push_front(len[0]);
677
12
678
12
                    // Message is now fully queued.
679
12
                    self.0.num_buffered_or_transmitted_messages += 1;
680
12
                    continue;
681
                }
682
                (1, false) => {
683
                    // Send `e, ee, s, es` and the libp2p-specific handshake.
684
685
                    // Process `e`.
686
12
                    let local_ephemeral_public_key =
687
12
                        x25519_dalek::PublicKey::from(&*self.0.local_ephemeral_private_key);
688
12
                    self.0
689
12
                        .pending_out_data
690
12
                        .extend(local_ephemeral_public_key.as_bytes());
691
12
                    mix_hash(&mut self.0.hash, local_ephemeral_public_key.as_bytes());
692
12
693
12
                    // Process `ee`. Call MixKey(DH(e, re)).
694
12
                    let HkdfOutput {
695
12
                        output1: chaining_key_update,
696
12
                        output2: key_update,
697
12
                    } = hkdf(
698
12
                        &self.0.chaining_key,
699
12
                        self.0
700
12
                            .local_ephemeral_private_key
701
12
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
702
12
                            .as_bytes(),
703
12
                    );
704
12
                    self.0.chaining_key = chaining_key_update;
705
12
                    self.0.cipher_state.key = key_update;
706
12
                    self.0.cipher_state.nonce = 0;
707
12
708
12
                    // Process `s`. Append EncryptAndHash(s.public_key) to the buffer.
709
12
                    let encrypted_static_public_key = self
710
12
                        .0
711
12
                        .cipher_state
712
12
                        .write_chachapoly_message_to_vec(
713
12
                            &*self.0.hash,
714
12
                            self.0.local_static_public_key.as_bytes(),
715
12
                        )
716
12
                        .unwrap();
717
12
                    self.0
718
12
                        .pending_out_data
719
12
                        .extend(encrypted_static_public_key.iter().copied());
720
12
                    mix_hash(&mut self.0.hash, &encrypted_static_public_key);
721
12
722
12
                    // Process `es`. Call MixKey(DH(s, re)).
723
12
                    let HkdfOutput {
724
12
                        output1: chaining_key_update,
725
12
                        output2: key_update,
726
12
                    } = hkdf(
727
12
                        &self.0.chaining_key,
728
12
                        self.0
729
12
                            .local_static_private_key
730
12
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
731
12
                            .as_bytes(),
732
12
                    );
733
12
                    self.0.chaining_key = chaining_key_update;
734
12
                    self.0.cipher_state.key = key_update;
735
12
                    self.0.cipher_state.nonce = 0;
736
12
737
12
                    // Add the libp2p handshake message.
738
12
                    let encrypted_libp2p_handshake = self
739
12
                        .0
740
12
                        .cipher_state
741
12
                        .write_chachapoly_message_to_vec(
742
12
                            &*self.0.hash,
743
12
                            &self.0.libp2p_handshake_message,
744
12
                        )
745
12
                        .unwrap();
746
12
                    self.0
747
12
                        .pending_out_data
748
12
                        .extend(encrypted_libp2p_handshake.iter().copied());
749
12
                    mix_hash(&mut self.0.hash, &encrypted_libp2p_handshake);
750
12
751
12
                    // Add the libp2p message length.
752
12
                    let len = u16::try_from(self.0.pending_out_data.len())
753
12
                        .unwrap()
754
12
                        .to_be_bytes();
755
12
                    self.0.pending_out_data.push_front(len[1]);
756
12
                    self.0.pending_out_data.push_front(len[0]);
757
12
758
12
                    // Message is now fully queued.
759
12
                    self.0.num_buffered_or_transmitted_messages += 1;
760
12
                    continue;
761
                }
762
                (2, true) => {
763
                    // Send `s, se` and the libp2p-specific handshake.
764
765
                    // Process `s`. Append EncryptAndHash(s.public_key) to the buffer.
766
12
                    let encrypted_static_public_key = self
767
12
                        .0
768
12
                        .cipher_state
769
12
                        .write_chachapoly_message_to_vec(
770
12
                            &*self.0.hash,
771
12
                            self.0.local_static_public_key.as_bytes(),
772
12
                        )
773
12
                        .unwrap();
774
12
                    self.0
775
12
                        .pending_out_data
776
12
                        .extend(encrypted_static_public_key.iter().copied());
777
12
                    mix_hash(&mut self.0.hash, &encrypted_static_public_key);
778
12
779
12
                    // Process `se`. Call MixKey(DH(s, re)).
780
12
                    let HkdfOutput {
781
12
                        output1: chaining_key_update,
782
12
                        output2: key_update,
783
12
                    } = hkdf(
784
12
                        &self.0.chaining_key,
785
12
                        self.0
786
12
                            .local_static_private_key
787
12
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
788
12
                            .as_bytes(),
789
12
                    );
790
12
                    self.0.chaining_key = chaining_key_update;
791
12
                    self.0.cipher_state.key = key_update;
792
12
                    self.0.cipher_state.nonce = 0;
793
12
794
12
                    // Add the libp2p handshake message.
795
12
                    let encrypted_libp2p_handshake = self
796
12
                        .0
797
12
                        .cipher_state
798
12
                        .write_chachapoly_message_to_vec(
799
12
                            &*self.0.hash,
800
12
                            &self.0.libp2p_handshake_message,
801
12
                        )
802
12
                        .unwrap();
803
12
                    self.0
804
12
                        .pending_out_data
805
12
                        .extend(encrypted_libp2p_handshake.iter().copied());
806
12
                    mix_hash(&mut self.0.hash, &encrypted_libp2p_handshake);
807
12
808
12
                    // Add the libp2p message length.
809
12
                    let len = u16::try_from(self.0.pending_out_data.len())
810
12
                        .unwrap()
811
12
                        .to_be_bytes();
812
12
                    self.0.pending_out_data.push_front(len[1]);
813
12
                    self.0.pending_out_data.push_front(len[0]);
814
12
815
12
                    // Message is now fully queued.
816
12
                    self.0.num_buffered_or_transmitted_messages += 1;
817
12
                    continue;
818
                }
819
76
                _ => {}
820
            }
821
822
            // Since we have no more data to write out, and that the handshake isn't finished yet,
823
            // the next step is necessarily receiving a message sent by the remote.
824
825
            // Grab the size of the next message, either from `self` or by extracting 2 bytes from
826
            // the incoming buffer.
827
42
            let next_in_message_size =
828
76
                if let Some(
next_in_message_size6
) = self.0.next_in_message_size {
829
6
                    next_in_message_size
830
                } else {
831
70
                    match read_write.incoming_bytes_take(2) {
832
36
                        Ok(Some(size_buffer)) => *self.0.next_in_message_size.insert(
833
36
                            u16::from_be_bytes(<[u8; 2]>::try_from(&size_buffer[..2]).unwrap()),
834
36
                        ),
835
                        Ok(None) => {
836
                            // Not enough data in incoming buffer.
837
34
                            return Ok(NoiseHandshake::InProgress(self));
838
                        }
839
                        Err(read_write::IncomingBytesTakeError::ReadClosed) => {
840
0
                            return Err(HandshakeError::ReadClosed)
841
                        }
842
                    }
843
                };
844
845
            // Extract the message from the incoming buffer.
846
36
            let available_message =
847
42
                match read_write.incoming_bytes_take(usize::from(next_in_message_size)) {
848
36
                    Ok(Some(available_message)) => {
849
36
                        self.0.next_in_message_size = None;
850
36
                        available_message
851
                    }
852
                    Ok(None) => {
853
                        // Not enough data in incoming buffer.
854
6
                        return Ok(NoiseHandshake::InProgress(self));
855
                    }
856
                    Err(read_write::IncomingBytesTakeError::ReadClosed) => {
857
0
                        return Err(HandshakeError::ReadClosed)
858
                    }
859
                };
860
861
            // How to parse the message depends on the current handshake phase.
862
36
            match (
863
36
                self.0.num_buffered_or_transmitted_messages,
864
36
                self.0.is_initiator,
865
36
            ) {
866
                (0, false) => {
867
                    // Receive `e` message from the remote.
868
                    self.0.remote_ephemeral_public_key = x25519_dalek::PublicKey::from(*{
869
                        // Because the remote hasn't authenticated us at this point, sending more
870
                        // data than what the protocol specifies is forbidden.
871
12
                        let mut parser = nom::combinator::all_consuming::<
872
12
                            _,
873
12
                            _,
874
12
                            (&[u8], nom::error::ErrorKind),
875
12
                            _,
876
12
                        >(nom::combinator::map(
877
12
                            nom::bytes::streaming::take(32u32),
878
12
                            |k| <&[u8; 32]>::try_from(k).unwrap(),
_RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs_0Be_
Line
Count
Source
878
7
                            |k| <&[u8; 32]>::try_from(k).unwrap(),
_RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writelEs_0Be_
Line
Count
Source
878
5
                            |k| <&[u8; 32]>::try_from(k).unwrap(),
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writepEs_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs_0CsiUjFBJteJ7x_17smoldot_full_node
879
12
                        ));
880
12
                        match parser(&available_message) {
881
12
                            Ok((_, out)) => out,
882
                            Err(_) => {
883
0
                                return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
884
                            }
885
                        }
886
                    });
887
12
                    mix_hash(
888
12
                        &mut self.0.hash,
889
12
                        self.0.remote_ephemeral_public_key.as_bytes(),
890
12
                    );
891
12
892
12
                    // Call MixHash(&[]) to process the empty payload.
893
12
                    mix_hash(&mut self.0.hash, &[]);
894
12
895
12
                    // Message has been fully processed.
896
12
                    self.0.num_buffered_or_transmitted_messages += 1;
897
12
                    continue;
898
                }
899
                (1, true) => {
900
                    // Receive `e, ee, s, es` and the libp2p-specific handshake from the remote.
901
                    let (
902
12
                        remote_ephemeral_public_key,
903
12
                        remote_static_public_key_encrypted,
904
12
                        libp2p_handshake_encrypted,
905
                    ) = {
906
                        // Because the remote hasn't fully authenticated us at this point, sending
907
                        // more data than what the protocol specifies is forbidden.
908
12
                        let mut parser = nom::combinator::all_consuming::<
909
12
                            _,
910
12
                            _,
911
12
                            (&[u8], nom::error::ErrorKind),
912
12
                            _,
913
12
                        >(nom::sequence::tuple((
914
12
                            nom::combinator::map(nom::bytes::streaming::take(32u32), |k| {
915
12
                                <&[u8; 32]>::try_from(k).unwrap()
916
12
                            }),
_RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs0_0Be_
Line
Count
Source
914
7
                            nom::combinator::map(nom::bytes::streaming::take(32u32), |k| {
915
7
                                <&[u8; 32]>::try_from(k).unwrap()
916
7
                            }),
_RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writelEs0_0Be_
Line
Count
Source
914
5
                            nom::combinator::map(nom::bytes::streaming::take(32u32), |k| {
915
5
                                <&[u8; 32]>::try_from(k).unwrap()
916
5
                            }),
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs0_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writepEs0_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs0_0CsiUjFBJteJ7x_17smoldot_full_node
917
12
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
918
12
                                <&[u8; 48]>::try_from(k).unwrap()
919
12
                            }),
_RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs1_0Be_
Line
Count
Source
917
7
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
918
7
                                <&[u8; 48]>::try_from(k).unwrap()
919
7
                            }),
_RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writelEs1_0Be_
Line
Count
Source
917
5
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
918
5
                                <&[u8; 48]>::try_from(k).unwrap()
919
5
                            }),
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs1_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writepEs1_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs1_0CsiUjFBJteJ7x_17smoldot_full_node
920
12
                            nom::combinator::rest,
921
12
                        )));
922
12
                        match parser(&available_message) {
923
12
                            Ok((_, out)) => out,
924
                            Err(_) => {
925
0
                                return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
926
                            }
927
                        }
928
                    };
929
930
                    // Process `e`.
931
12
                    self.0.remote_ephemeral_public_key =
932
12
                        x25519_dalek::PublicKey::from(*remote_ephemeral_public_key);
933
12
                    mix_hash(
934
12
                        &mut self.0.hash,
935
12
                        self.0.remote_ephemeral_public_key.as_bytes(),
936
12
                    );
937
12
938
12
                    // Process `ee`. Call MixKey(DH(e, re)).
939
12
                    let HkdfOutput {
940
12
                        output1: chaining_key_update,
941
12
                        output2: key_update,
942
12
                    } = hkdf(
943
12
                        &self.0.chaining_key,
944
12
                        self.0
945
12
                            .local_ephemeral_private_key
946
12
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
947
12
                            .as_bytes(),
948
12
                    );
949
12
                    self.0.chaining_key = chaining_key_update;
950
12
                    self.0.cipher_state.key = key_update;
951
12
                    self.0.cipher_state.nonce = 0;
952
12
953
12
                    // Process `s`.
954
12
                    self.0.remote_static_public_key = x25519_dalek::PublicKey::from(
955
12
                        self.0
956
12
                            .cipher_state
957
12
                            .read_chachapoly_message_to_array(
958
12
                                &*self.0.hash,
959
12
                                remote_static_public_key_encrypted,
960
12
                            )
961
12
                            .map_err(HandshakeError::Cipher)
?0
,
962
                    );
963
12
                    mix_hash(&mut self.0.hash, remote_static_public_key_encrypted);
964
12
965
12
                    // Process `es`. Call MixKey(DH(e, rs)).
966
12
                    let HkdfOutput {
967
12
                        output1: chaining_key_update,
968
12
                        output2: key_update,
969
12
                    } = hkdf(
970
12
                        &self.0.chaining_key,
971
12
                        self.0
972
12
                            .local_ephemeral_private_key
973
12
                            .diffie_hellman(&self.0.remote_static_public_key)
974
12
                            .as_bytes(),
975
12
                    );
976
12
                    self.0.chaining_key = chaining_key_update;
977
12
                    self.0.cipher_state.key = key_update;
978
12
                    self.0.cipher_state.nonce = 0;
979
980
                    // Process the libp2p-specific handshake.
981
                    self.0.remote_public_key = Some({
982
12
                        let libp2p_handshake_decrypted = self
983
12
                            .0
984
12
                            .cipher_state
985
12
                            .read_chachapoly_message_to_vec(
986
12
                                &*self.0.hash,
987
12
                                libp2p_handshake_encrypted,
988
12
                            )
989
12
                            .map_err(HandshakeError::Cipher)
?0
;
990
12
                        let (libp2p_key, libp2p_signature) = {
991
12
                            let mut parser =
992
12
                                nom::combinator::all_consuming::<
993
12
                                    _,
994
12
                                    _,
995
12
                                    (&[u8], nom::error::ErrorKind),
996
12
                                    _,
997
12
                                >(protobuf::message_decode! {
998
0
                                    #[required] key = 1 => protobuf::bytes_tag_decode,
999
0
                                    #[required] sig = 2 => protobuf::bytes_tag_decode,
1000
12
                                });
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs5_00Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs5_0s_0Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writelEs5_00Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writelEs5_0s_0Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs5_00CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs5_0s_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writepEs5_00Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writepEs5_0s_0Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs5_00CsiUjFBJteJ7x_17smoldot_full_node
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs5_0s_0CsiUjFBJteJ7x_17smoldot_full_node
1001
12
                            match parser(&libp2p_handshake_decrypted) {
1002
12
                                Ok((_, out)) => (out.key, out.sig),
1003
                                Err(_) => {
1004
0
                                    return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
1005
                                }
1006
                            }
1007
                        };
1008
12
                        let remote_public_key = PublicKey::from_protobuf_encoding(libp2p_key)
1009
12
                            .map_err(|_| 
HandshakeError::InvalidKey0
)
?0
;
Unexecuted instantiation: _RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs2_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writelEs2_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs2_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writepEs2_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs2_0CsiUjFBJteJ7x_17smoldot_full_node
1010
12
                        remote_public_key
1011
12
                            .verify(
1012
12
                                &[
1013
12
                                    &b"noise-libp2p-static-key:"[..],
1014
12
                                    &self.0.remote_static_public_key.as_bytes()[..],
1015
12
                                ]
1016
12
                                .concat(),
1017
12
                                libp2p_signature,
1018
12
                            )
1019
12
                            .map_err(HandshakeError::SignatureVerificationFailed)
?0
;
1020
12
                        remote_public_key
1021
12
                    });
1022
12
                    mix_hash(&mut self.0.hash, libp2p_handshake_encrypted);
1023
12
1024
12
                    // Message has been fully processed.
1025
12
                    self.0.num_buffered_or_transmitted_messages += 1;
1026
12
                    continue;
1027
                }
1028
                (2, false) => {
1029
                    // Receive `s, se` and the libp2p-specific handshake from the remote.
1030
12
                    let (remote_static_public_key_encrypted, libp2p_handshake_encrypted) = {
1031
                        // The noise and libp2p-noise specifications clearly define a noise
1032
                        // handshake message and a noise transport message as two different things.
1033
                        // While the remote could in theory send post-handshake
1034
                        // application-specific data in this message, in practice it is forbidden.
1035
12
                        let mut parser = nom::combinator::all_consuming::<
1036
12
                            _,
1037
12
                            _,
1038
12
                            (&[u8], nom::error::ErrorKind),
1039
12
                            _,
1040
12
                        >(nom::sequence::tuple((
1041
12
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
1042
12
                                <&[u8; 48]>::try_from(k).unwrap()
1043
12
                            }),
_RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs3_0Be_
Line
Count
Source
1041
7
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
1042
7
                                <&[u8; 48]>::try_from(k).unwrap()
1043
7
                            }),
_RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writelEs3_0Be_
Line
Count
Source
1041
5
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
1042
5
                                <&[u8; 48]>::try_from(k).unwrap()
1043
5
                            }),
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs3_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writepEs3_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs3_0CsiUjFBJteJ7x_17smoldot_full_node
1044
12
                            nom::combinator::rest,
1045
12
                        )));
1046
12
                        match parser(&available_message) {
1047
12
                            Ok((_, out)) => out,
1048
                            Err(_) => {
1049
0
                                return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
1050
                            }
1051
                        }
1052
                    };
1053
1054
                    // Process `s`.
1055
                    self.0.remote_static_public_key = x25519_dalek::PublicKey::from(
1056
12
                        self.0
1057
12
                            .cipher_state
1058
12
                            .read_chachapoly_message_to_array(
1059
12
                                &*self.0.hash,
1060
12
                                remote_static_public_key_encrypted,
1061
12
                            )
1062
12
                            .map_err(HandshakeError::Cipher)
?0
,
1063
                    );
1064
12
                    mix_hash(&mut self.0.hash, remote_static_public_key_encrypted);
1065
12
1066
12
                    // Process `se`. Call MixKey(DH(e, rs)).
1067
12
                    let HkdfOutput {
1068
12
                        output1: chaining_key_update,
1069
12
                        output2: key_update,
1070
12
                    } = hkdf(
1071
12
                        &self.0.chaining_key,
1072
12
                        self.0
1073
12
                            .local_ephemeral_private_key
1074
12
                            .clone()
1075
12
                            .diffie_hellman(&self.0.remote_static_public_key)
1076
12
                            .as_bytes(),
1077
12
                    );
1078
12
                    self.0.chaining_key = chaining_key_update;
1079
12
                    self.0.cipher_state.key = key_update;
1080
12
                    self.0.cipher_state.nonce = 0;
1081
1082
                    // Process the libp2p-specific handshake.
1083
                    self.0.remote_public_key = Some({
1084
12
                        let libp2p_handshake_decrypted = self
1085
12
                            .0
1086
12
                            .cipher_state
1087
12
                            .read_chachapoly_message_to_vec(
1088
12
                                &*self.0.hash,
1089
12
                                libp2p_handshake_encrypted,
1090
12
                            )
1091
12
                            .map_err(HandshakeError::Cipher)
?0
;
1092
12
                        let (libp2p_key, libp2p_signature) = {
1093
12
                            let mut parser =
1094
12
                                nom::combinator::all_consuming::<
1095
12
                                    _,
1096
12
                                    _,
1097
12
                                    (&[u8], nom::error::ErrorKind),
1098
12
                                    _,
1099
12
                                >(protobuf::message_decode! {
1100
0
                                    #[required] key = 1 => protobuf::bytes_tag_decode,
1101
0
                                    #[required] sig = 2 => protobuf::bytes_tag_decode,
1102
12
                                });
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs6_00Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs6_0s_0Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writelEs6_00Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writelEs6_0s_0Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs6_00CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs6_0s_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writepEs6_00Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writepEs6_0s_0Bg_
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs6_00CsiUjFBJteJ7x_17smoldot_full_node
Unexecuted instantiation: _RNCNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtBa_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs6_0s_0CsiUjFBJteJ7x_17smoldot_full_node
1103
12
                            match parser(&libp2p_handshake_decrypted) {
1104
12
                                Ok((_, out)) => (out.key, out.sig),
1105
                                Err(_) => {
1106
0
                                    return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
1107
                                }
1108
                            }
1109
                        };
1110
12
                        let remote_public_key = PublicKey::from_protobuf_encoding(libp2p_key)
1111
12
                            .map_err(|_| 
HandshakeError::InvalidKey0
)
?0
;
Unexecuted instantiation: _RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs4_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writelEs4_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEs4_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writepEs4_0Be_
Unexecuted instantiation: _RNCINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantEs4_0CsiUjFBJteJ7x_17smoldot_full_node
1112
12
                        remote_public_key
1113
12
                            .verify(
1114
12
                                &[
1115
12
                                    &b"noise-libp2p-static-key:"[..],
1116
12
                                    &self.0.remote_static_public_key.as_bytes()[..],
1117
12
                                ]
1118
12
                                .concat(),
1119
12
                                libp2p_signature,
1120
12
                            )
1121
12
                            .map_err(HandshakeError::SignatureVerificationFailed)
?0
;
1122
12
                        remote_public_key
1123
12
                    });
1124
12
                    mix_hash(&mut self.0.hash, libp2p_handshake_encrypted);
1125
12
1126
12
                    // Message has been fully processed.
1127
12
                    self.0.num_buffered_or_transmitted_messages += 1;
1128
12
                    continue;
1129
                }
1130
                _ => {
1131
                    // Any other state was handled earlier in the function.
1132
0
                    unreachable!()
1133
                }
1134
            }
1135
        }
1136
72
    }
_RINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB6_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationEBc_
Line
Count
Source
592
35
    pub fn read_write<TNow>(
593
35
        mut self,
594
35
        read_write: &mut ReadWrite<TNow>,
595
35
    ) -> Result<NoiseHandshake, HandshakeError> {
596
77
        loop {
597
77
            // Write out the data currently buffered waiting to be written out.
598
77
            // If we didn't finish writing our payload, don't do anything more and return now.
599
77
            // Don't even read the data from the remote.
600
77
            read_write.write_from_vec_deque(&mut self.0.pending_out_data);
601
77
            if !self.0.pending_out_data.is_empty() {
602
0
                if read_write.write_bytes_queueable.is_none() {
603
0
                    return Err(HandshakeError::WriteClosed);
604
0
                }
605
0
                return Ok(NoiseHandshake::InProgress(self));
606
77
            }
607
77
608
77
            // If the handshake has finished, we return successfully here.
609
77
            if self.0.num_buffered_or_transmitted_messages == 3 {
610
14
                debug_assert!(self.0.pending_out_data.is_empty());
611
14
                debug_assert!(self.0.next_in_message_size.is_none());
612
613
                // Perform the `Split()`.
614
                let HkdfOutput {
615
14
                    output1: init_to_resp,
616
14
                    output2: resp_to_init,
617
14
                } = hkdf(&self.0.chaining_key, &[]);
618
14
                let (out_key, in_key) = match self.0.is_initiator {
619
7
                    true => (init_to_resp, resp_to_init),
620
7
                    false => (resp_to_init, init_to_resp),
621
                };
622
14
                return Ok(NoiseHandshake::Success {
623
14
                    cipher: Noise {
624
14
                        is_initiator: self.0.is_initiator,
625
14
                        out_cipher_state: CipherState {
626
14
                            key: out_key,
627
14
                            nonce: 0,
628
14
                            nonce_has_overflowed: false,
629
14
                        },
630
14
                        in_cipher_state: CipherState {
631
14
                            key: in_key,
632
14
                            nonce: 0,
633
14
                            nonce_has_overflowed: false,
634
14
                        },
635
14
                        rx_buffer_decrypted: Vec::with_capacity(65535 - 16),
636
14
                        next_in_message_size: None,
637
14
                        inner_stream_expected_incoming_bytes: 0,
638
14
                    },
639
14
                    remote_peer_id: {
640
14
                        // The logic of this module guarantees that `remote_peer_id` has
641
14
                        // been set during the handshake.
642
14
                        self.0
643
14
                            .remote_public_key
644
14
                            .take()
645
14
                            .unwrap_or_else(|| unreachable!())
646
14
                            .into_peer_id()
647
14
                    },
648
14
                });
649
63
            }
650
63
651
63
            // If the handshake is in a phase where we need to send out more data, queue said
652
63
            // data to `pending_out_data` and continue.
653
63
            match (
654
63
                self.0.num_buffered_or_transmitted_messages,
655
63
                self.0.is_initiator,
656
63
            ) {
657
                (0, true) => {
658
                    // Send `e`, the ephemeral local public key.
659
660
                    // Process `e`.
661
7
                    let local_ephemeral_public_key =
662
7
                        x25519_dalek::PublicKey::from(&*self.0.local_ephemeral_private_key);
663
7
                    self.0
664
7
                        .pending_out_data
665
7
                        .extend(local_ephemeral_public_key.as_bytes());
666
7
                    mix_hash(&mut self.0.hash, local_ephemeral_public_key.as_bytes());
667
7
668
7
                    // Call MixHash(&[]) to process the empty payload.
669
7
                    mix_hash(&mut self.0.hash, &[]);
670
7
671
7
                    // Add the libp2p message length.
672
7
                    let len = u16::try_from(self.0.pending_out_data.len())
673
7
                        .unwrap()
674
7
                        .to_be_bytes();
675
7
                    self.0.pending_out_data.push_front(len[1]);
676
7
                    self.0.pending_out_data.push_front(len[0]);
677
7
678
7
                    // Message is now fully queued.
679
7
                    self.0.num_buffered_or_transmitted_messages += 1;
680
7
                    continue;
681
                }
682
                (1, false) => {
683
                    // Send `e, ee, s, es` and the libp2p-specific handshake.
684
685
                    // Process `e`.
686
7
                    let local_ephemeral_public_key =
687
7
                        x25519_dalek::PublicKey::from(&*self.0.local_ephemeral_private_key);
688
7
                    self.0
689
7
                        .pending_out_data
690
7
                        .extend(local_ephemeral_public_key.as_bytes());
691
7
                    mix_hash(&mut self.0.hash, local_ephemeral_public_key.as_bytes());
692
7
693
7
                    // Process `ee`. Call MixKey(DH(e, re)).
694
7
                    let HkdfOutput {
695
7
                        output1: chaining_key_update,
696
7
                        output2: key_update,
697
7
                    } = hkdf(
698
7
                        &self.0.chaining_key,
699
7
                        self.0
700
7
                            .local_ephemeral_private_key
701
7
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
702
7
                            .as_bytes(),
703
7
                    );
704
7
                    self.0.chaining_key = chaining_key_update;
705
7
                    self.0.cipher_state.key = key_update;
706
7
                    self.0.cipher_state.nonce = 0;
707
7
708
7
                    // Process `s`. Append EncryptAndHash(s.public_key) to the buffer.
709
7
                    let encrypted_static_public_key = self
710
7
                        .0
711
7
                        .cipher_state
712
7
                        .write_chachapoly_message_to_vec(
713
7
                            &*self.0.hash,
714
7
                            self.0.local_static_public_key.as_bytes(),
715
7
                        )
716
7
                        .unwrap();
717
7
                    self.0
718
7
                        .pending_out_data
719
7
                        .extend(encrypted_static_public_key.iter().copied());
720
7
                    mix_hash(&mut self.0.hash, &encrypted_static_public_key);
721
7
722
7
                    // Process `es`. Call MixKey(DH(s, re)).
723
7
                    let HkdfOutput {
724
7
                        output1: chaining_key_update,
725
7
                        output2: key_update,
726
7
                    } = hkdf(
727
7
                        &self.0.chaining_key,
728
7
                        self.0
729
7
                            .local_static_private_key
730
7
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
731
7
                            .as_bytes(),
732
7
                    );
733
7
                    self.0.chaining_key = chaining_key_update;
734
7
                    self.0.cipher_state.key = key_update;
735
7
                    self.0.cipher_state.nonce = 0;
736
7
737
7
                    // Add the libp2p handshake message.
738
7
                    let encrypted_libp2p_handshake = self
739
7
                        .0
740
7
                        .cipher_state
741
7
                        .write_chachapoly_message_to_vec(
742
7
                            &*self.0.hash,
743
7
                            &self.0.libp2p_handshake_message,
744
7
                        )
745
7
                        .unwrap();
746
7
                    self.0
747
7
                        .pending_out_data
748
7
                        .extend(encrypted_libp2p_handshake.iter().copied());
749
7
                    mix_hash(&mut self.0.hash, &encrypted_libp2p_handshake);
750
7
751
7
                    // Add the libp2p message length.
752
7
                    let len = u16::try_from(self.0.pending_out_data.len())
753
7
                        .unwrap()
754
7
                        .to_be_bytes();
755
7
                    self.0.pending_out_data.push_front(len[1]);
756
7
                    self.0.pending_out_data.push_front(len[0]);
757
7
758
7
                    // Message is now fully queued.
759
7
                    self.0.num_buffered_or_transmitted_messages += 1;
760
7
                    continue;
761
                }
762
                (2, true) => {
763
                    // Send `s, se` and the libp2p-specific handshake.
764
765
                    // Process `s`. Append EncryptAndHash(s.public_key) to the buffer.
766
7
                    let encrypted_static_public_key = self
767
7
                        .0
768
7
                        .cipher_state
769
7
                        .write_chachapoly_message_to_vec(
770
7
                            &*self.0.hash,
771
7
                            self.0.local_static_public_key.as_bytes(),
772
7
                        )
773
7
                        .unwrap();
774
7
                    self.0
775
7
                        .pending_out_data
776
7
                        .extend(encrypted_static_public_key.iter().copied());
777
7
                    mix_hash(&mut self.0.hash, &encrypted_static_public_key);
778
7
779
7
                    // Process `se`. Call MixKey(DH(s, re)).
780
7
                    let HkdfOutput {
781
7
                        output1: chaining_key_update,
782
7
                        output2: key_update,
783
7
                    } = hkdf(
784
7
                        &self.0.chaining_key,
785
7
                        self.0
786
7
                            .local_static_private_key
787
7
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
788
7
                            .as_bytes(),
789
7
                    );
790
7
                    self.0.chaining_key = chaining_key_update;
791
7
                    self.0.cipher_state.key = key_update;
792
7
                    self.0.cipher_state.nonce = 0;
793
7
794
7
                    // Add the libp2p handshake message.
795
7
                    let encrypted_libp2p_handshake = self
796
7
                        .0
797
7
                        .cipher_state
798
7
                        .write_chachapoly_message_to_vec(
799
7
                            &*self.0.hash,
800
7
                            &self.0.libp2p_handshake_message,
801
7
                        )
802
7
                        .unwrap();
803
7
                    self.0
804
7
                        .pending_out_data
805
7
                        .extend(encrypted_libp2p_handshake.iter().copied());
806
7
                    mix_hash(&mut self.0.hash, &encrypted_libp2p_handshake);
807
7
808
7
                    // Add the libp2p message length.
809
7
                    let len = u16::try_from(self.0.pending_out_data.len())
810
7
                        .unwrap()
811
7
                        .to_be_bytes();
812
7
                    self.0.pending_out_data.push_front(len[1]);
813
7
                    self.0.pending_out_data.push_front(len[0]);
814
7
815
7
                    // Message is now fully queued.
816
7
                    self.0.num_buffered_or_transmitted_messages += 1;
817
7
                    continue;
818
                }
819
42
                _ => {}
820
            }
821
822
            // Since we have no more data to write out, and that the handshake isn't finished yet,
823
            // the next step is necessarily receiving a message sent by the remote.
824
825
            // Grab the size of the next message, either from `self` or by extracting 2 bytes from
826
            // the incoming buffer.
827
21
            let next_in_message_size =
828
42
                if let Some(
next_in_message_size0
) = self.0.next_in_message_size {
829
0
                    next_in_message_size
830
                } else {
831
42
                    match read_write.incoming_bytes_take(2) {
832
21
                        Ok(Some(size_buffer)) => *self.0.next_in_message_size.insert(
833
21
                            u16::from_be_bytes(<[u8; 2]>::try_from(&size_buffer[..2]).unwrap()),
834
21
                        ),
835
                        Ok(None) => {
836
                            // Not enough data in incoming buffer.
837
21
                            return Ok(NoiseHandshake::InProgress(self));
838
                        }
839
                        Err(read_write::IncomingBytesTakeError::ReadClosed) => {
840
0
                            return Err(HandshakeError::ReadClosed)
841
                        }
842
                    }
843
                };
844
845
            // Extract the message from the incoming buffer.
846
21
            let available_message =
847
21
                match read_write.incoming_bytes_take(usize::from(next_in_message_size)) {
848
21
                    Ok(Some(available_message)) => {
849
21
                        self.0.next_in_message_size = None;
850
21
                        available_message
851
                    }
852
                    Ok(None) => {
853
                        // Not enough data in incoming buffer.
854
0
                        return Ok(NoiseHandshake::InProgress(self));
855
                    }
856
                    Err(read_write::IncomingBytesTakeError::ReadClosed) => {
857
0
                        return Err(HandshakeError::ReadClosed)
858
                    }
859
                };
860
861
            // How to parse the message depends on the current handshake phase.
862
21
            match (
863
21
                self.0.num_buffered_or_transmitted_messages,
864
21
                self.0.is_initiator,
865
21
            ) {
866
                (0, false) => {
867
                    // Receive `e` message from the remote.
868
                    self.0.remote_ephemeral_public_key = x25519_dalek::PublicKey::from(*{
869
                        // Because the remote hasn't authenticated us at this point, sending more
870
                        // data than what the protocol specifies is forbidden.
871
7
                        let mut parser = nom::combinator::all_consuming::<
872
7
                            _,
873
7
                            _,
874
7
                            (&[u8], nom::error::ErrorKind),
875
7
                            _,
876
7
                        >(nom::combinator::map(
877
7
                            nom::bytes::streaming::take(32u32),
878
7
                            |k| <&[u8; 32]>::try_from(k).unwrap(),
879
7
                        ));
880
7
                        match parser(&available_message) {
881
7
                            Ok((_, out)) => out,
882
                            Err(_) => {
883
0
                                return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
884
                            }
885
                        }
886
                    });
887
7
                    mix_hash(
888
7
                        &mut self.0.hash,
889
7
                        self.0.remote_ephemeral_public_key.as_bytes(),
890
7
                    );
891
7
892
7
                    // Call MixHash(&[]) to process the empty payload.
893
7
                    mix_hash(&mut self.0.hash, &[]);
894
7
895
7
                    // Message has been fully processed.
896
7
                    self.0.num_buffered_or_transmitted_messages += 1;
897
7
                    continue;
898
                }
899
                (1, true) => {
900
                    // Receive `e, ee, s, es` and the libp2p-specific handshake from the remote.
901
                    let (
902
7
                        remote_ephemeral_public_key,
903
7
                        remote_static_public_key_encrypted,
904
7
                        libp2p_handshake_encrypted,
905
                    ) = {
906
                        // Because the remote hasn't fully authenticated us at this point, sending
907
                        // more data than what the protocol specifies is forbidden.
908
7
                        let mut parser = nom::combinator::all_consuming::<
909
7
                            _,
910
7
                            _,
911
7
                            (&[u8], nom::error::ErrorKind),
912
7
                            _,
913
7
                        >(nom::sequence::tuple((
914
7
                            nom::combinator::map(nom::bytes::streaming::take(32u32), |k| {
915
                                <&[u8; 32]>::try_from(k).unwrap()
916
7
                            }),
917
7
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
918
                                <&[u8; 48]>::try_from(k).unwrap()
919
7
                            }),
920
7
                            nom::combinator::rest,
921
7
                        )));
922
7
                        match parser(&available_message) {
923
7
                            Ok((_, out)) => out,
924
                            Err(_) => {
925
0
                                return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
926
                            }
927
                        }
928
                    };
929
930
                    // Process `e`.
931
7
                    self.0.remote_ephemeral_public_key =
932
7
                        x25519_dalek::PublicKey::from(*remote_ephemeral_public_key);
933
7
                    mix_hash(
934
7
                        &mut self.0.hash,
935
7
                        self.0.remote_ephemeral_public_key.as_bytes(),
936
7
                    );
937
7
938
7
                    // Process `ee`. Call MixKey(DH(e, re)).
939
7
                    let HkdfOutput {
940
7
                        output1: chaining_key_update,
941
7
                        output2: key_update,
942
7
                    } = hkdf(
943
7
                        &self.0.chaining_key,
944
7
                        self.0
945
7
                            .local_ephemeral_private_key
946
7
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
947
7
                            .as_bytes(),
948
7
                    );
949
7
                    self.0.chaining_key = chaining_key_update;
950
7
                    self.0.cipher_state.key = key_update;
951
7
                    self.0.cipher_state.nonce = 0;
952
7
953
7
                    // Process `s`.
954
7
                    self.0.remote_static_public_key = x25519_dalek::PublicKey::from(
955
7
                        self.0
956
7
                            .cipher_state
957
7
                            .read_chachapoly_message_to_array(
958
7
                                &*self.0.hash,
959
7
                                remote_static_public_key_encrypted,
960
7
                            )
961
7
                            .map_err(HandshakeError::Cipher)
?0
,
962
                    );
963
7
                    mix_hash(&mut self.0.hash, remote_static_public_key_encrypted);
964
7
965
7
                    // Process `es`. Call MixKey(DH(e, rs)).
966
7
                    let HkdfOutput {
967
7
                        output1: chaining_key_update,
968
7
                        output2: key_update,
969
7
                    } = hkdf(
970
7
                        &self.0.chaining_key,
971
7
                        self.0
972
7
                            .local_ephemeral_private_key
973
7
                            .diffie_hellman(&self.0.remote_static_public_key)
974
7
                            .as_bytes(),
975
7
                    );
976
7
                    self.0.chaining_key = chaining_key_update;
977
7
                    self.0.cipher_state.key = key_update;
978
7
                    self.0.cipher_state.nonce = 0;
979
980
                    // Process the libp2p-specific handshake.
981
                    self.0.remote_public_key = Some({
982
7
                        let libp2p_handshake_decrypted = self
983
7
                            .0
984
7
                            .cipher_state
985
7
                            .read_chachapoly_message_to_vec(
986
7
                                &*self.0.hash,
987
7
                                libp2p_handshake_encrypted,
988
7
                            )
989
7
                            .map_err(HandshakeError::Cipher)
?0
;
990
7
                        let (libp2p_key, libp2p_signature) = {
991
7
                            let mut parser =
992
7
                                nom::combinator::all_consuming::<
993
7
                                    _,
994
7
                                    _,
995
7
                                    (&[u8], nom::error::ErrorKind),
996
7
                                    _,
997
7
                                >(protobuf::message_decode! {
998
                                    #[required] key = 1 => protobuf::bytes_tag_decode,
999
                                    #[required] sig = 2 => protobuf::bytes_tag_decode,
1000
7
                                });
1001
7
                            match parser(&libp2p_handshake_decrypted) {
1002
7
                                Ok((_, out)) => (out.key, out.sig),
1003
                                Err(_) => {
1004
0
                                    return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
1005
                                }
1006
                            }
1007
                        };
1008
7
                        let remote_public_key = PublicKey::from_protobuf_encoding(libp2p_key)
1009
7
                            .map_err(|_| HandshakeError::InvalidKey)
?0
;
1010
7
                        remote_public_key
1011
7
                            .verify(
1012
7
                                &[
1013
7
                                    &b"noise-libp2p-static-key:"[..],
1014
7
                                    &self.0.remote_static_public_key.as_bytes()[..],
1015
7
                                ]
1016
7
                                .concat(),
1017
7
                                libp2p_signature,
1018
7
                            )
1019
7
                            .map_err(HandshakeError::SignatureVerificationFailed)
?0
;
1020
7
                        remote_public_key
1021
7
                    });
1022
7
                    mix_hash(&mut self.0.hash, libp2p_handshake_encrypted);
1023
7
1024
7
                    // Message has been fully processed.
1025
7
                    self.0.num_buffered_or_transmitted_messages += 1;
1026
7
                    continue;
1027
                }
1028
                (2, false) => {
1029
                    // Receive `s, se` and the libp2p-specific handshake from the remote.
1030
7
                    let (remote_static_public_key_encrypted, libp2p_handshake_encrypted) = {
1031
                        // The noise and libp2p-noise specifications clearly define a noise
1032
                        // handshake message and a noise transport message as two different things.
1033
                        // While the remote could in theory send post-handshake
1034
                        // application-specific data in this message, in practice it is forbidden.
1035
7
                        let mut parser = nom::combinator::all_consuming::<
1036
7
                            _,
1037
7
                            _,
1038
7
                            (&[u8], nom::error::ErrorKind),
1039
7
                            _,
1040
7
                        >(nom::sequence::tuple((
1041
7
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
1042
                                <&[u8; 48]>::try_from(k).unwrap()
1043
7
                            }),
1044
7
                            nom::combinator::rest,
1045
7
                        )));
1046
7
                        match parser(&available_message) {
1047
7
                            Ok((_, out)) => out,
1048
                            Err(_) => {
1049
0
                                return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
1050
                            }
1051
                        }
1052
                    };
1053
1054
                    // Process `s`.
1055
                    self.0.remote_static_public_key = x25519_dalek::PublicKey::from(
1056
7
                        self.0
1057
7
                            .cipher_state
1058
7
                            .read_chachapoly_message_to_array(
1059
7
                                &*self.0.hash,
1060
7
                                remote_static_public_key_encrypted,
1061
7
                            )
1062
7
                            .map_err(HandshakeError::Cipher)
?0
,
1063
                    );
1064
7
                    mix_hash(&mut self.0.hash, remote_static_public_key_encrypted);
1065
7
1066
7
                    // Process `se`. Call MixKey(DH(e, rs)).
1067
7
                    let HkdfOutput {
1068
7
                        output1: chaining_key_update,
1069
7
                        output2: key_update,
1070
7
                    } = hkdf(
1071
7
                        &self.0.chaining_key,
1072
7
                        self.0
1073
7
                            .local_ephemeral_private_key
1074
7
                            .clone()
1075
7
                            .diffie_hellman(&self.0.remote_static_public_key)
1076
7
                            .as_bytes(),
1077
7
                    );
1078
7
                    self.0.chaining_key = chaining_key_update;
1079
7
                    self.0.cipher_state.key = key_update;
1080
7
                    self.0.cipher_state.nonce = 0;
1081
1082
                    // Process the libp2p-specific handshake.
1083
                    self.0.remote_public_key = Some({
1084
7
                        let libp2p_handshake_decrypted = self
1085
7
                            .0
1086
7
                            .cipher_state
1087
7
                            .read_chachapoly_message_to_vec(
1088
7
                                &*self.0.hash,
1089
7
                                libp2p_handshake_encrypted,
1090
7
                            )
1091
7
                            .map_err(HandshakeError::Cipher)
?0
;
1092
7
                        let (libp2p_key, libp2p_signature) = {
1093
7
                            let mut parser =
1094
7
                                nom::combinator::all_consuming::<
1095
7
                                    _,
1096
7
                                    _,
1097
7
                                    (&[u8], nom::error::ErrorKind),
1098
7
                                    _,
1099
7
                                >(protobuf::message_decode! {
1100
                                    #[required] key = 1 => protobuf::bytes_tag_decode,
1101
                                    #[required] sig = 2 => protobuf::bytes_tag_decode,
1102
7
                                });
1103
7
                            match parser(&libp2p_handshake_decrypted) {
1104
7
                                Ok((_, out)) => (out.key, out.sig),
1105
                                Err(_) => {
1106
0
                                    return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
1107
                                }
1108
                            }
1109
                        };
1110
7
                        let remote_public_key = PublicKey::from_protobuf_encoding(libp2p_key)
1111
7
                            .map_err(|_| HandshakeError::InvalidKey)
?0
;
1112
7
                        remote_public_key
1113
7
                            .verify(
1114
7
                                &[
1115
7
                                    &b"noise-libp2p-static-key:"[..],
1116
7
                                    &self.0.remote_static_public_key.as_bytes()[..],
1117
7
                                ]
1118
7
                                .concat(),
1119
7
                                libp2p_signature,
1120
7
                            )
1121
7
                            .map_err(HandshakeError::SignatureVerificationFailed)
?0
;
1122
7
                        remote_public_key
1123
7
                    });
1124
7
                    mix_hash(&mut self.0.hash, libp2p_handshake_encrypted);
1125
7
1126
7
                    // Message has been fully processed.
1127
7
                    self.0.num_buffered_or_transmitted_messages += 1;
1128
7
                    continue;
1129
                }
1130
                _ => {
1131
                    // Any other state was handled earlier in the function.
1132
0
                    unreachable!()
1133
                }
1134
            }
1135
        }
1136
35
    }
_RINvMs6_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB6_19HandshakeInProgress10read_writelEBc_
Line
Count
Source
592
37
    pub fn read_write<TNow>(
593
37
        mut self,
594
37
        read_write: &mut ReadWrite<TNow>,
595
37
    ) -> Result<NoiseHandshake, HandshakeError> {
596
67
        loop {
597
67
            // Write out the data currently buffered waiting to be written out.
598
67
            // If we didn't finish writing our payload, don't do anything more and return now.
599
67
            // Don't even read the data from the remote.
600
67
            read_write.write_from_vec_deque(&mut self.0.pending_out_data);
601
67
            if !self.0.pending_out_data.is_empty() {
602
8
                if read_write.write_bytes_queueable.is_none() {
603
0
                    return Err(HandshakeError::WriteClosed);
604
8
                }
605
8
                return Ok(NoiseHandshake::InProgress(self));
606
59
            }
607
59
608
59
            // If the handshake has finished, we return successfully here.
609
59
            if self.0.num_buffered_or_transmitted_messages == 3 {
610
10
                debug_assert!(self.0.pending_out_data.is_empty());
611
10
                debug_assert!(self.0.next_in_message_size.is_none());
612
613
                // Perform the `Split()`.
614
                let HkdfOutput {
615
10
                    output1: init_to_resp,
616
10
                    output2: resp_to_init,
617
10
                } = hkdf(&self.0.chaining_key, &[]);
618
10
                let (out_key, in_key) = match self.0.is_initiator {
619
5
                    true => (init_to_resp, resp_to_init),
620
5
                    false => (resp_to_init, init_to_resp),
621
                };
622
10
                return Ok(NoiseHandshake::Success {
623
10
                    cipher: Noise {
624
10
                        is_initiator: self.0.is_initiator,
625
10
                        out_cipher_state: CipherState {
626
10
                            key: out_key,
627
10
                            nonce: 0,
628
10
                            nonce_has_overflowed: false,
629
10
                        },
630
10
                        in_cipher_state: CipherState {
631
10
                            key: in_key,
632
10
                            nonce: 0,
633
10
                            nonce_has_overflowed: false,
634
10
                        },
635
10
                        rx_buffer_decrypted: Vec::with_capacity(65535 - 16),
636
10
                        next_in_message_size: None,
637
10
                        inner_stream_expected_incoming_bytes: 0,
638
10
                    },
639
10
                    remote_peer_id: {
640
10
                        // The logic of this module guarantees that `remote_peer_id` has
641
10
                        // been set during the handshake.
642
10
                        self.0
643
10
                            .remote_public_key
644
10
                            .take()
645
10
                            .unwrap_or_else(|| unreachable!())
646
10
                            .into_peer_id()
647
10
                    },
648
10
                });
649
49
            }
650
49
651
49
            // If the handshake is in a phase where we need to send out more data, queue said
652
49
            // data to `pending_out_data` and continue.
653
49
            match (
654
49
                self.0.num_buffered_or_transmitted_messages,
655
49
                self.0.is_initiator,
656
49
            ) {
657
                (0, true) => {
658
                    // Send `e`, the ephemeral local public key.
659
660
                    // Process `e`.
661
5
                    let local_ephemeral_public_key =
662
5
                        x25519_dalek::PublicKey::from(&*self.0.local_ephemeral_private_key);
663
5
                    self.0
664
5
                        .pending_out_data
665
5
                        .extend(local_ephemeral_public_key.as_bytes());
666
5
                    mix_hash(&mut self.0.hash, local_ephemeral_public_key.as_bytes());
667
5
668
5
                    // Call MixHash(&[]) to process the empty payload.
669
5
                    mix_hash(&mut self.0.hash, &[]);
670
5
671
5
                    // Add the libp2p message length.
672
5
                    let len = u16::try_from(self.0.pending_out_data.len())
673
5
                        .unwrap()
674
5
                        .to_be_bytes();
675
5
                    self.0.pending_out_data.push_front(len[1]);
676
5
                    self.0.pending_out_data.push_front(len[0]);
677
5
678
5
                    // Message is now fully queued.
679
5
                    self.0.num_buffered_or_transmitted_messages += 1;
680
5
                    continue;
681
                }
682
                (1, false) => {
683
                    // Send `e, ee, s, es` and the libp2p-specific handshake.
684
685
                    // Process `e`.
686
5
                    let local_ephemeral_public_key =
687
5
                        x25519_dalek::PublicKey::from(&*self.0.local_ephemeral_private_key);
688
5
                    self.0
689
5
                        .pending_out_data
690
5
                        .extend(local_ephemeral_public_key.as_bytes());
691
5
                    mix_hash(&mut self.0.hash, local_ephemeral_public_key.as_bytes());
692
5
693
5
                    // Process `ee`. Call MixKey(DH(e, re)).
694
5
                    let HkdfOutput {
695
5
                        output1: chaining_key_update,
696
5
                        output2: key_update,
697
5
                    } = hkdf(
698
5
                        &self.0.chaining_key,
699
5
                        self.0
700
5
                            .local_ephemeral_private_key
701
5
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
702
5
                            .as_bytes(),
703
5
                    );
704
5
                    self.0.chaining_key = chaining_key_update;
705
5
                    self.0.cipher_state.key = key_update;
706
5
                    self.0.cipher_state.nonce = 0;
707
5
708
5
                    // Process `s`. Append EncryptAndHash(s.public_key) to the buffer.
709
5
                    let encrypted_static_public_key = self
710
5
                        .0
711
5
                        .cipher_state
712
5
                        .write_chachapoly_message_to_vec(
713
5
                            &*self.0.hash,
714
5
                            self.0.local_static_public_key.as_bytes(),
715
5
                        )
716
5
                        .unwrap();
717
5
                    self.0
718
5
                        .pending_out_data
719
5
                        .extend(encrypted_static_public_key.iter().copied());
720
5
                    mix_hash(&mut self.0.hash, &encrypted_static_public_key);
721
5
722
5
                    // Process `es`. Call MixKey(DH(s, re)).
723
5
                    let HkdfOutput {
724
5
                        output1: chaining_key_update,
725
5
                        output2: key_update,
726
5
                    } = hkdf(
727
5
                        &self.0.chaining_key,
728
5
                        self.0
729
5
                            .local_static_private_key
730
5
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
731
5
                            .as_bytes(),
732
5
                    );
733
5
                    self.0.chaining_key = chaining_key_update;
734
5
                    self.0.cipher_state.key = key_update;
735
5
                    self.0.cipher_state.nonce = 0;
736
5
737
5
                    // Add the libp2p handshake message.
738
5
                    let encrypted_libp2p_handshake = self
739
5
                        .0
740
5
                        .cipher_state
741
5
                        .write_chachapoly_message_to_vec(
742
5
                            &*self.0.hash,
743
5
                            &self.0.libp2p_handshake_message,
744
5
                        )
745
5
                        .unwrap();
746
5
                    self.0
747
5
                        .pending_out_data
748
5
                        .extend(encrypted_libp2p_handshake.iter().copied());
749
5
                    mix_hash(&mut self.0.hash, &encrypted_libp2p_handshake);
750
5
751
5
                    // Add the libp2p message length.
752
5
                    let len = u16::try_from(self.0.pending_out_data.len())
753
5
                        .unwrap()
754
5
                        .to_be_bytes();
755
5
                    self.0.pending_out_data.push_front(len[1]);
756
5
                    self.0.pending_out_data.push_front(len[0]);
757
5
758
5
                    // Message is now fully queued.
759
5
                    self.0.num_buffered_or_transmitted_messages += 1;
760
5
                    continue;
761
                }
762
                (2, true) => {
763
                    // Send `s, se` and the libp2p-specific handshake.
764
765
                    // Process `s`. Append EncryptAndHash(s.public_key) to the buffer.
766
5
                    let encrypted_static_public_key = self
767
5
                        .0
768
5
                        .cipher_state
769
5
                        .write_chachapoly_message_to_vec(
770
5
                            &*self.0.hash,
771
5
                            self.0.local_static_public_key.as_bytes(),
772
5
                        )
773
5
                        .unwrap();
774
5
                    self.0
775
5
                        .pending_out_data
776
5
                        .extend(encrypted_static_public_key.iter().copied());
777
5
                    mix_hash(&mut self.0.hash, &encrypted_static_public_key);
778
5
779
5
                    // Process `se`. Call MixKey(DH(s, re)).
780
5
                    let HkdfOutput {
781
5
                        output1: chaining_key_update,
782
5
                        output2: key_update,
783
5
                    } = hkdf(
784
5
                        &self.0.chaining_key,
785
5
                        self.0
786
5
                            .local_static_private_key
787
5
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
788
5
                            .as_bytes(),
789
5
                    );
790
5
                    self.0.chaining_key = chaining_key_update;
791
5
                    self.0.cipher_state.key = key_update;
792
5
                    self.0.cipher_state.nonce = 0;
793
5
794
5
                    // Add the libp2p handshake message.
795
5
                    let encrypted_libp2p_handshake = self
796
5
                        .0
797
5
                        .cipher_state
798
5
                        .write_chachapoly_message_to_vec(
799
5
                            &*self.0.hash,
800
5
                            &self.0.libp2p_handshake_message,
801
5
                        )
802
5
                        .unwrap();
803
5
                    self.0
804
5
                        .pending_out_data
805
5
                        .extend(encrypted_libp2p_handshake.iter().copied());
806
5
                    mix_hash(&mut self.0.hash, &encrypted_libp2p_handshake);
807
5
808
5
                    // Add the libp2p message length.
809
5
                    let len = u16::try_from(self.0.pending_out_data.len())
810
5
                        .unwrap()
811
5
                        .to_be_bytes();
812
5
                    self.0.pending_out_data.push_front(len[1]);
813
5
                    self.0.pending_out_data.push_front(len[0]);
814
5
815
5
                    // Message is now fully queued.
816
5
                    self.0.num_buffered_or_transmitted_messages += 1;
817
5
                    continue;
818
                }
819
34
                _ => {}
820
            }
821
822
            // Since we have no more data to write out, and that the handshake isn't finished yet,
823
            // the next step is necessarily receiving a message sent by the remote.
824
825
            // Grab the size of the next message, either from `self` or by extracting 2 bytes from
826
            // the incoming buffer.
827
21
            let next_in_message_size =
828
34
                if let Some(
next_in_message_size6
) = self.0.next_in_message_size {
829
6
                    next_in_message_size
830
                } else {
831
28
                    match read_write.incoming_bytes_take(2) {
832
15
                        Ok(Some(size_buffer)) => *self.0.next_in_message_size.insert(
833
15
                            u16::from_be_bytes(<[u8; 2]>::try_from(&size_buffer[..2]).unwrap()),
834
15
                        ),
835
                        Ok(None) => {
836
                            // Not enough data in incoming buffer.
837
13
                            return Ok(NoiseHandshake::InProgress(self));
838
                        }
839
                        Err(read_write::IncomingBytesTakeError::ReadClosed) => {
840
0
                            return Err(HandshakeError::ReadClosed)
841
                        }
842
                    }
843
                };
844
845
            // Extract the message from the incoming buffer.
846
15
            let available_message =
847
21
                match read_write.incoming_bytes_take(usize::from(next_in_message_size)) {
848
15
                    Ok(Some(available_message)) => {
849
15
                        self.0.next_in_message_size = None;
850
15
                        available_message
851
                    }
852
                    Ok(None) => {
853
                        // Not enough data in incoming buffer.
854
6
                        return Ok(NoiseHandshake::InProgress(self));
855
                    }
856
                    Err(read_write::IncomingBytesTakeError::ReadClosed) => {
857
0
                        return Err(HandshakeError::ReadClosed)
858
                    }
859
                };
860
861
            // How to parse the message depends on the current handshake phase.
862
15
            match (
863
15
                self.0.num_buffered_or_transmitted_messages,
864
15
                self.0.is_initiator,
865
15
            ) {
866
                (0, false) => {
867
                    // Receive `e` message from the remote.
868
                    self.0.remote_ephemeral_public_key = x25519_dalek::PublicKey::from(*{
869
                        // Because the remote hasn't authenticated us at this point, sending more
870
                        // data than what the protocol specifies is forbidden.
871
5
                        let mut parser = nom::combinator::all_consuming::<
872
5
                            _,
873
5
                            _,
874
5
                            (&[u8], nom::error::ErrorKind),
875
5
                            _,
876
5
                        >(nom::combinator::map(
877
5
                            nom::bytes::streaming::take(32u32),
878
5
                            |k| <&[u8; 32]>::try_from(k).unwrap(),
879
5
                        ));
880
5
                        match parser(&available_message) {
881
5
                            Ok((_, out)) => out,
882
                            Err(_) => {
883
0
                                return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
884
                            }
885
                        }
886
                    });
887
5
                    mix_hash(
888
5
                        &mut self.0.hash,
889
5
                        self.0.remote_ephemeral_public_key.as_bytes(),
890
5
                    );
891
5
892
5
                    // Call MixHash(&[]) to process the empty payload.
893
5
                    mix_hash(&mut self.0.hash, &[]);
894
5
895
5
                    // Message has been fully processed.
896
5
                    self.0.num_buffered_or_transmitted_messages += 1;
897
5
                    continue;
898
                }
899
                (1, true) => {
900
                    // Receive `e, ee, s, es` and the libp2p-specific handshake from the remote.
901
                    let (
902
5
                        remote_ephemeral_public_key,
903
5
                        remote_static_public_key_encrypted,
904
5
                        libp2p_handshake_encrypted,
905
                    ) = {
906
                        // Because the remote hasn't fully authenticated us at this point, sending
907
                        // more data than what the protocol specifies is forbidden.
908
5
                        let mut parser = nom::combinator::all_consuming::<
909
5
                            _,
910
5
                            _,
911
5
                            (&[u8], nom::error::ErrorKind),
912
5
                            _,
913
5
                        >(nom::sequence::tuple((
914
5
                            nom::combinator::map(nom::bytes::streaming::take(32u32), |k| {
915
                                <&[u8; 32]>::try_from(k).unwrap()
916
5
                            }),
917
5
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
918
                                <&[u8; 48]>::try_from(k).unwrap()
919
5
                            }),
920
5
                            nom::combinator::rest,
921
5
                        )));
922
5
                        match parser(&available_message) {
923
5
                            Ok((_, out)) => out,
924
                            Err(_) => {
925
0
                                return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
926
                            }
927
                        }
928
                    };
929
930
                    // Process `e`.
931
5
                    self.0.remote_ephemeral_public_key =
932
5
                        x25519_dalek::PublicKey::from(*remote_ephemeral_public_key);
933
5
                    mix_hash(
934
5
                        &mut self.0.hash,
935
5
                        self.0.remote_ephemeral_public_key.as_bytes(),
936
5
                    );
937
5
938
5
                    // Process `ee`. Call MixKey(DH(e, re)).
939
5
                    let HkdfOutput {
940
5
                        output1: chaining_key_update,
941
5
                        output2: key_update,
942
5
                    } = hkdf(
943
5
                        &self.0.chaining_key,
944
5
                        self.0
945
5
                            .local_ephemeral_private_key
946
5
                            .diffie_hellman(&self.0.remote_ephemeral_public_key)
947
5
                            .as_bytes(),
948
5
                    );
949
5
                    self.0.chaining_key = chaining_key_update;
950
5
                    self.0.cipher_state.key = key_update;
951
5
                    self.0.cipher_state.nonce = 0;
952
5
953
5
                    // Process `s`.
954
5
                    self.0.remote_static_public_key = x25519_dalek::PublicKey::from(
955
5
                        self.0
956
5
                            .cipher_state
957
5
                            .read_chachapoly_message_to_array(
958
5
                                &*self.0.hash,
959
5
                                remote_static_public_key_encrypted,
960
5
                            )
961
5
                            .map_err(HandshakeError::Cipher)
?0
,
962
                    );
963
5
                    mix_hash(&mut self.0.hash, remote_static_public_key_encrypted);
964
5
965
5
                    // Process `es`. Call MixKey(DH(e, rs)).
966
5
                    let HkdfOutput {
967
5
                        output1: chaining_key_update,
968
5
                        output2: key_update,
969
5
                    } = hkdf(
970
5
                        &self.0.chaining_key,
971
5
                        self.0
972
5
                            .local_ephemeral_private_key
973
5
                            .diffie_hellman(&self.0.remote_static_public_key)
974
5
                            .as_bytes(),
975
5
                    );
976
5
                    self.0.chaining_key = chaining_key_update;
977
5
                    self.0.cipher_state.key = key_update;
978
5
                    self.0.cipher_state.nonce = 0;
979
980
                    // Process the libp2p-specific handshake.
981
                    self.0.remote_public_key = Some({
982
5
                        let libp2p_handshake_decrypted = self
983
5
                            .0
984
5
                            .cipher_state
985
5
                            .read_chachapoly_message_to_vec(
986
5
                                &*self.0.hash,
987
5
                                libp2p_handshake_encrypted,
988
5
                            )
989
5
                            .map_err(HandshakeError::Cipher)
?0
;
990
5
                        let (libp2p_key, libp2p_signature) = {
991
5
                            let mut parser =
992
5
                                nom::combinator::all_consuming::<
993
5
                                    _,
994
5
                                    _,
995
5
                                    (&[u8], nom::error::ErrorKind),
996
5
                                    _,
997
5
                                >(protobuf::message_decode! {
998
                                    #[required] key = 1 => protobuf::bytes_tag_decode,
999
                                    #[required] sig = 2 => protobuf::bytes_tag_decode,
1000
5
                                });
1001
5
                            match parser(&libp2p_handshake_decrypted) {
1002
5
                                Ok((_, out)) => (out.key, out.sig),
1003
                                Err(_) => {
1004
0
                                    return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
1005
                                }
1006
                            }
1007
                        };
1008
5
                        let remote_public_key = PublicKey::from_protobuf_encoding(libp2p_key)
1009
5
                            .map_err(|_| HandshakeError::InvalidKey)
?0
;
1010
5
                        remote_public_key
1011
5
                            .verify(
1012
5
                                &[
1013
5
                                    &b"noise-libp2p-static-key:"[..],
1014
5
                                    &self.0.remote_static_public_key.as_bytes()[..],
1015
5
                                ]
1016
5
                                .concat(),
1017
5
                                libp2p_signature,
1018
5
                            )
1019
5
                            .map_err(HandshakeError::SignatureVerificationFailed)
?0
;
1020
5
                        remote_public_key
1021
5
                    });
1022
5
                    mix_hash(&mut self.0.hash, libp2p_handshake_encrypted);
1023
5
1024
5
                    // Message has been fully processed.
1025
5
                    self.0.num_buffered_or_transmitted_messages += 1;
1026
5
                    continue;
1027
                }
1028
                (2, false) => {
1029
                    // Receive `s, se` and the libp2p-specific handshake from the remote.
1030
5
                    let (remote_static_public_key_encrypted, libp2p_handshake_encrypted) = {
1031
                        // The noise and libp2p-noise specifications clearly define a noise
1032
                        // handshake message and a noise transport message as two different things.
1033
                        // While the remote could in theory send post-handshake
1034
                        // application-specific data in this message, in practice it is forbidden.
1035
5
                        let mut parser = nom::combinator::all_consuming::<
1036
5
                            _,
1037
5
                            _,
1038
5
                            (&[u8], nom::error::ErrorKind),
1039
5
                            _,
1040
5
                        >(nom::sequence::tuple((
1041
5
                            nom::combinator::map(nom::bytes::streaming::take(48u32), |k| {
1042
                                <&[u8; 48]>::try_from(k).unwrap()
1043
5
                            }),
1044
5
                            nom::combinator::rest,
1045
5
                        )));
1046
5
                        match parser(&available_message) {
1047
5
                            Ok((_, out)) => out,
1048
                            Err(_) => {
1049
0
                                return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
1050
                            }
1051
                        }
1052
                    };
1053
1054
                    // Process `s`.
1055
                    self.0.remote_static_public_key = x25519_dalek::PublicKey::from(
1056
5
                        self.0
1057
5
                            .cipher_state
1058
5
                            .read_chachapoly_message_to_array(
1059
5
                                &*self.0.hash,
1060
5
                                remote_static_public_key_encrypted,
1061
5
                            )
1062
5
                            .map_err(HandshakeError::Cipher)
?0
,
1063
                    );
1064
5
                    mix_hash(&mut self.0.hash, remote_static_public_key_encrypted);
1065
5
1066
5
                    // Process `se`. Call MixKey(DH(e, rs)).
1067
5
                    let HkdfOutput {
1068
5
                        output1: chaining_key_update,
1069
5
                        output2: key_update,
1070
5
                    } = hkdf(
1071
5
                        &self.0.chaining_key,
1072
5
                        self.0
1073
5
                            .local_ephemeral_private_key
1074
5
                            .clone()
1075
5
                            .diffie_hellman(&self.0.remote_static_public_key)
1076
5
                            .as_bytes(),
1077
5
                    );
1078
5
                    self.0.chaining_key = chaining_key_update;
1079
5
                    self.0.cipher_state.key = key_update;
1080
5
                    self.0.cipher_state.nonce = 0;
1081
1082
                    // Process the libp2p-specific handshake.
1083
                    self.0.remote_public_key = Some({
1084
5
                        let libp2p_handshake_decrypted = self
1085
5
                            .0
1086
5
                            .cipher_state
1087
5
                            .read_chachapoly_message_to_vec(
1088
5
                                &*self.0.hash,
1089
5
                                libp2p_handshake_encrypted,
1090
5
                            )
1091
5
                            .map_err(HandshakeError::Cipher)
?0
;
1092
5
                        let (libp2p_key, libp2p_signature) = {
1093
5
                            let mut parser =
1094
5
                                nom::combinator::all_consuming::<
1095
5
                                    _,
1096
5
                                    _,
1097
5
                                    (&[u8], nom::error::ErrorKind),
1098
5
                                    _,
1099
5
                                >(protobuf::message_decode! {
1100
                                    #[required] key = 1 => protobuf::bytes_tag_decode,
1101
                                    #[required] sig = 2 => protobuf::bytes_tag_decode,
1102
5
                                });
1103
5
                            match parser(&libp2p_handshake_decrypted) {
1104
5
                                Ok((_, out)) => (out.key, out.sig),
1105
                                Err(_) => {
1106
0
                                    return Err(HandshakeError::PayloadDecode(PayloadDecodeError))
1107
                                }
1108
                            }
1109
                        };
1110
5
                        let remote_public_key = PublicKey::from_protobuf_encoding(libp2p_key)
1111
5
                            .map_err(|_| HandshakeError::InvalidKey)
?0
;
1112
5
                        remote_public_key
1113
5
                            .verify(
1114
5
                                &[
1115
5
                                    &b"noise-libp2p-static-key:"[..],
1116
5
                                    &self.0.remote_static_public_key.as_bytes()[..],
1117
5
                                ]
1118
5
                                .concat(),
1119
5
                                libp2p_signature,
1120
5
                            )
1121
5
                            .map_err(HandshakeError::SignatureVerificationFailed)
?0
;
1122
5
                        remote_public_key
1123
5
                    });
1124
5
                    mix_hash(&mut self.0.hash, libp2p_handshake_encrypted);
1125
5
1126
5
                    // Message has been fully processed.
1127
5
                    self.0.num_buffered_or_transmitted_messages += 1;
1128
5
                    continue;
1129
                }
1130
                _ => {
1131
                    // Any other state was handled earlier in the function.
1132
0
                    unreachable!()
1133
                }
1134
            }
1135
        }
1136
37
    }
Unexecuted instantiation: _RINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_19HandshakeInProgress10read_writeNtNtCsaYZPK01V26L_4core4time8DurationECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_19HandshakeInProgress10read_writepEBc_
Unexecuted instantiation: _RINvMs6_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_19HandshakeInProgress10read_writeNtNtCsbpXXxgr6u8g_3std4time7InstantECsiUjFBJteJ7x_17smoldot_full_node
1137
}
1138
1139
impl fmt::Debug for HandshakeInProgress {
1140
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1141
0
        f.debug_struct("HandshakeInProgress").finish()
1142
0
    }
Unexecuted instantiation: _RNvXs7_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_19HandshakeInProgressNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXs7_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_19HandshakeInProgressNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
1143
}
1144
1145
/// Potential error during the noise handshake.
1146
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsb_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_14HandshakeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsb_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_14HandshakeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
1147
pub enum HandshakeError {
1148
    /// Reading side of the connection is closed. The handshake can't proceed further.
1149
    ReadClosed,
1150
    /// Writing side of the connection is closed. The handshake can't proceed further.
1151
    WriteClosed,
1152
    /// Error in the decryption state machine.
1153
    #[display(fmt = "Cipher error: {_0}")]
1154
    Cipher(CipherError),
1155
    /// Failed to decode the payload as the libp2p-extension-to-noise payload.
1156
    #[display(fmt = "Failed to decode payload as the libp2p-extension-to-noise payload: {_0}")]
1157
    PayloadDecode(PayloadDecodeError),
1158
    /// Key passed as part of the payload failed to decode into a libp2p public key.
1159
    InvalidKey,
1160
    /// Signature of the noise public key by the libp2p key failed.
1161
    #[display(fmt = "Signature of the noise public key by the libp2p key failed.")]
1162
    SignatureVerificationFailed(SignatureVerifyFailed),
1163
}
1164
1165
/// Error while encrypting data.
1166
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsd_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_12EncryptErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsd_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_12EncryptErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
1167
#[display(fmt = "Error while encrypting the Noise payload")]
1168
pub enum EncryptError {
1169
    /// The nonce has overflowed because too many messages have been exchanged. This error is a
1170
    /// normal situation and will happen given sufficient time.
1171
    NonceOverflow,
1172
}
1173
1174
/// Error while decoding data.
1175
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsf_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_11CipherErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsf_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_11CipherErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
1176
#[display(fmt = "Error while decrypting the Noise payload")]
1177
pub enum CipherError {
1178
    /// Message is too small. This is likely caused by a bug either in this code or in the remote's
1179
    /// code.
1180
    MissingHmac,
1181
    /// Authentication data doesn't match what is expected.
1182
    HmacInvalid,
1183
    /// The nonce has overflowed because too many messages have been exchanged. This error is a
1184
    /// normal situation and will happen given sufficient time.
1185
    NonceOverflow,
1186
}
1187
1188
/// Error while decoding the handshake.
1189
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsh_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_18PayloadDecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsh_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_18PayloadDecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
1190
pub struct PayloadDecodeError;
1191
1192
struct CipherState {
1193
    key: zeroize::Zeroizing<[u8; 32]>,
1194
    nonce: u64,
1195
    nonce_has_overflowed: bool,
1196
}
1197
1198
impl CipherState {
1199
    /// Accepts a list of input buffers, and returns output buffers that contain the encrypted data
1200
    /// and the HMAC will be written.
1201
    ///
1202
    /// Does *not* include the libp2p-specific message length prefix.
1203
141
    fn write_chachapoly_message(
1204
141
        &'_ mut self,
1205
141
        associated_data: &[u8],
1206
141
        decrypted_buffers: impl Iterator<Item = Vec<u8>>,
1207
141
    ) -> Result<impl Iterator<Item = Vec<u8>>, EncryptError> {
1208
141
        if self.nonce_has_overflowed {
1209
0
            return Err(EncryptError::NonceOverflow);
1210
141
        }
1211
141
1212
141
        let (mut cipher, mac) = self.prepare(associated_data);
1213
141
        let associated_data_len = associated_data.len();
1214
141
1215
141
        // Increment the nonce by 1. This is done ahead of time in order to be sure that the same
1216
141
        // nonce is never re-used even if the API user drops the returned iterator before it ends.
1217
141
        (self.nonce, self.nonce_has_overflowed) = self.nonce.overflowing_add(1);
1218
141
1219
141
        // The difficulty in this function implementation is that the cipher operates on 64 bytes
1220
141
        // blocks (in other words, the data passed to them must have a size multiple of 64), and
1221
141
        // unfortunately the input buffers might be weirdly aligned.
1222
141
        // To overcome this, when there's an alignment issue, we copy the data to a contiguous
1223
141
        // slice.
1224
141
1225
141
        // Each input buffer is encrypted in place as much as possible. Due to alignment issues,
1226
141
        // each input buffer is split in three parts: the data that is appended to the previous
1227
141
        // buffer's data in order to align it, the data that can be encrypted in place, and the
1228
141
        // data that must be prepanded to the start of the next buffer.
1229
141
        // Furthermore, note that the third part of the last buffer can always be encrypted in
1230
141
        // place.
1231
141
1232
141
        // The implementation below requires `decrypted_buffers` to be peekable.
1233
141
        let mut decrypted_buffers = decrypted_buffers.peekable();
1234
141
        // Counter for total input decrypted data increased when iterating over the input.
1235
141
        // Necessary at the very end of the calculation.
1236
141
        let mut total_decrypted_data = 0;
1237
141
        // Data that was copied from the end of the previous buffer.
1238
141
        // TODO: ideally we would avoid copying the end of the previous buffer, and instead only copy the start of the next one, but this means that we couldn't return concrete `Vec`s anymore, and this API change is complicated
1239
141
        let mut overlapping_data = Vec::new();
1240
141
        // `None` if the HMAC has already been returned from the iterator.
1241
141
        let mut mac = Some(mac);
1242
141
1243
141
        // Iterator being returned.
1244
564
        Ok(iter::from_fn(move || {
1245
720
            loop {
1246
720
                debug_assert!(overlapping_data.len() < 64);
1247
1248
                // Return if iterator has finished.
1249
720
                let Some(
mac_deref579
) = mac.as_mut() else {
1250
141
                    return None;
1251
                };
1252
1253
579
                if !overlapping_data.is_empty() {
1254
                    // Copy data from the start of the next buffer to the end
1255
                    // of `overlapping_data`.
1256
297
                    if let Some(
next_buffer156
) = decrypted_buffers.peek_mut() {
1257
156
                        let missing_data_for_full_frame = 64 - overlapping_data.len();
1258
156
                        if next_buffer.len() >= missing_data_for_full_frame {
1259
                            // Enough data in next buffer to fill a frame in `overlapping_data`.
1260
                            // Extract data from the next buffer.
1261
0
                            overlapping_data
1262
0
                                .extend_from_slice(&next_buffer[..missing_data_for_full_frame]);
1263
0
                            next_buffer.copy_within(missing_data_for_full_frame.., 0);
1264
0
                            next_buffer.truncate(next_buffer.len() - missing_data_for_full_frame);
1265
0
1266
0
                            // Encrypt `overlapping_data` in place and return it.
1267
0
                            chacha20::cipher::StreamCipher::apply_keystream(
1268
0
                                &mut cipher,
1269
0
                                &mut overlapping_data,
1270
0
                            );
1271
0
                            poly1305::universal_hash::UniversalHash::update_padded(
1272
0
                                mac_deref,
1273
0
                                &overlapping_data,
1274
0
                            );
1275
0
                            debug_assert_eq!(overlapping_data.len(), 64);
1276
0
                            total_decrypted_data += 64;
1277
0
                            return Some(mem::take(&mut overlapping_data));
1278
156
                        } else {
1279
156
                            // Not enough data in next buffer to fill `overlapping_data`.
1280
156
                            // Copy the data and continue looping.
1281
156
                            overlapping_data.extend_from_slice(next_buffer);
1282
156
                            let _ = decrypted_buffers.next();
1283
156
                        }
1284
                    } else {
1285
                        // Input is empty. `overlapping_data` is the last buffer.
1286
141
                        chacha20::cipher::StreamCipher::apply_keystream(
1287
141
                            &mut cipher,
1288
141
                            &mut overlapping_data,
1289
141
                        );
1290
141
                        poly1305::universal_hash::UniversalHash::update_padded(
1291
141
                            mac_deref,
1292
141
                            &overlapping_data,
1293
141
                        );
1294
141
                        total_decrypted_data += overlapping_data.len();
1295
141
                        return Some(mem::take(&mut overlapping_data));
1296
                    }
1297
282
                } else if let Some(
mut buffer141
) = decrypted_buffers.next() {
1298
                    // Number of bytes of `next_buffer` that can be encrypted in place.
1299
141
                    let encryptable_in_place = 64 * (buffer.len() / 64);
1300
141
1301
141
                    // Perform the encryption.
1302
141
                    chacha20::cipher::StreamCipher::apply_keystream(
1303
141
                        &mut cipher,
1304
141
                        &mut buffer[..encryptable_in_place],
1305
141
                    );
1306
141
                    poly1305::universal_hash::UniversalHash::update_padded(
1307
141
                        mac_deref,
1308
141
                        &buffer[..encryptable_in_place],
1309
141
                    );
1310
141
1311
141
                    // Copy the non-encryptable-in-place data to `overlapping_data`.
1312
141
                    if encryptable_in_place != buffer.len() {
1313
141
                        overlapping_data.reserve(64);
1314
141
                        overlapping_data.extend_from_slice(&buffer[encryptable_in_place..]);
1315
141
                        buffer.truncate(encryptable_in_place);
1316
141
                    }
0
1317
1318
                    // And return.
1319
141
                    total_decrypted_data += encryptable_in_place;
1320
141
                    return Some(buffer);
1321
                } else {
1322
                    // No more encrypted data to return.
1323
1324
                    // Update the MAC with the length of the associated data and input data.
1325
141
                    let mut block =
1326
141
                        poly1305::universal_hash::generic_array::GenericArray::default();
1327
141
                    block[..8].copy_from_slice(
1328
141
                        &u64::try_from(associated_data_len).unwrap().to_le_bytes(),
1329
141
                    );
1330
141
                    block[8..].copy_from_slice(
1331
141
                        &u64::try_from(total_decrypted_data).unwrap().to_le_bytes(),
1332
141
                    );
1333
141
                    poly1305::universal_hash::UniversalHash::update(mac_deref, &[block]);
1334
141
1335
141
                    // Return the HMAC.
1336
141
                    let mac_bytes =
1337
141
                        poly1305::universal_hash::UniversalHash::finalize(mac.take().unwrap())
1338
141
                            .to_vec();
1339
141
                    return Some(mac_bytes);
1340
                }
1341
            }
1342
564
        }
))141
_RNCINvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_11CipherState24write_chachapoly_messageINtNtNtCsdZExvAaxgia_5alloc3vec5drain5DrainINtB1L_3VechEEE0Be_
Line
Count
Source
1244
372
        Ok(iter::from_fn(move || {
1245
528
            loop {
1246
528
                debug_assert!(overlapping_data.len() < 64);
1247
1248
                // Return if iterator has finished.
1249
528
                let Some(
mac_deref435
) = mac.as_mut() else {
1250
93
                    return None;
1251
                };
1252
1253
435
                if !overlapping_data.is_empty() {
1254
                    // Copy data from the start of the next buffer to the end
1255
                    // of `overlapping_data`.
1256
249
                    if let Some(
next_buffer156
) = decrypted_buffers.peek_mut() {
1257
156
                        let missing_data_for_full_frame = 64 - overlapping_data.len();
1258
156
                        if next_buffer.len() >= missing_data_for_full_frame {
1259
                            // Enough data in next buffer to fill a frame in `overlapping_data`.
1260
                            // Extract data from the next buffer.
1261
0
                            overlapping_data
1262
0
                                .extend_from_slice(&next_buffer[..missing_data_for_full_frame]);
1263
0
                            next_buffer.copy_within(missing_data_for_full_frame.., 0);
1264
0
                            next_buffer.truncate(next_buffer.len() - missing_data_for_full_frame);
1265
0
1266
0
                            // Encrypt `overlapping_data` in place and return it.
1267
0
                            chacha20::cipher::StreamCipher::apply_keystream(
1268
0
                                &mut cipher,
1269
0
                                &mut overlapping_data,
1270
0
                            );
1271
0
                            poly1305::universal_hash::UniversalHash::update_padded(
1272
0
                                mac_deref,
1273
0
                                &overlapping_data,
1274
0
                            );
1275
0
                            debug_assert_eq!(overlapping_data.len(), 64);
1276
0
                            total_decrypted_data += 64;
1277
0
                            return Some(mem::take(&mut overlapping_data));
1278
156
                        } else {
1279
156
                            // Not enough data in next buffer to fill `overlapping_data`.
1280
156
                            // Copy the data and continue looping.
1281
156
                            overlapping_data.extend_from_slice(next_buffer);
1282
156
                            let _ = decrypted_buffers.next();
1283
156
                        }
1284
                    } else {
1285
                        // Input is empty. `overlapping_data` is the last buffer.
1286
93
                        chacha20::cipher::StreamCipher::apply_keystream(
1287
93
                            &mut cipher,
1288
93
                            &mut overlapping_data,
1289
93
                        );
1290
93
                        poly1305::universal_hash::UniversalHash::update_padded(
1291
93
                            mac_deref,
1292
93
                            &overlapping_data,
1293
93
                        );
1294
93
                        total_decrypted_data += overlapping_data.len();
1295
93
                        return Some(mem::take(&mut overlapping_data));
1296
                    }
1297
186
                } else if let Some(
mut buffer93
) = decrypted_buffers.next() {
1298
                    // Number of bytes of `next_buffer` that can be encrypted in place.
1299
93
                    let encryptable_in_place = 64 * (buffer.len() / 64);
1300
93
1301
93
                    // Perform the encryption.
1302
93
                    chacha20::cipher::StreamCipher::apply_keystream(
1303
93
                        &mut cipher,
1304
93
                        &mut buffer[..encryptable_in_place],
1305
93
                    );
1306
93
                    poly1305::universal_hash::UniversalHash::update_padded(
1307
93
                        mac_deref,
1308
93
                        &buffer[..encryptable_in_place],
1309
93
                    );
1310
93
1311
93
                    // Copy the non-encryptable-in-place data to `overlapping_data`.
1312
93
                    if encryptable_in_place != buffer.len() {
1313
93
                        overlapping_data.reserve(64);
1314
93
                        overlapping_data.extend_from_slice(&buffer[encryptable_in_place..]);
1315
93
                        buffer.truncate(encryptable_in_place);
1316
93
                    }
0
1317
1318
                    // And return.
1319
93
                    total_decrypted_data += encryptable_in_place;
1320
93
                    return Some(buffer);
1321
                } else {
1322
                    // No more encrypted data to return.
1323
1324
                    // Update the MAC with the length of the associated data and input data.
1325
93
                    let mut block =
1326
93
                        poly1305::universal_hash::generic_array::GenericArray::default();
1327
93
                    block[..8].copy_from_slice(
1328
93
                        &u64::try_from(associated_data_len).unwrap().to_le_bytes(),
1329
93
                    );
1330
93
                    block[8..].copy_from_slice(
1331
93
                        &u64::try_from(total_decrypted_data).unwrap().to_le_bytes(),
1332
93
                    );
1333
93
                    poly1305::universal_hash::UniversalHash::update(mac_deref, &[block]);
1334
93
1335
93
                    // Return the HMAC.
1336
93
                    let mac_bytes =
1337
93
                        poly1305::universal_hash::UniversalHash::finalize(mac.take().unwrap())
1338
93
                            .to_vec();
1339
93
                    return Some(mac_bytes);
1340
                }
1341
            }
1342
372
        }))
_RNCINvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB8_11CipherState24write_chachapoly_messageINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceINtNtCsdZExvAaxgia_5alloc3vec3VechEEE0Be_
Line
Count
Source
1244
192
        Ok(iter::from_fn(move || {
1245
192
            loop {
1246
192
                debug_assert!(overlapping_data.len() < 64);
1247
1248
                // Return if iterator has finished.
1249
192
                let Some(
mac_deref144
) = mac.as_mut() else {
1250
48
                    return None;
1251
                };
1252
1253
144
                if !overlapping_data.is_empty() {
1254
                    // Copy data from the start of the next buffer to the end
1255
                    // of `overlapping_data`.
1256
48
                    if let Some(
next_buffer0
) = decrypted_buffers.peek_mut() {
1257
0
                        let missing_data_for_full_frame = 64 - overlapping_data.len();
1258
0
                        if next_buffer.len() >= missing_data_for_full_frame {
1259
                            // Enough data in next buffer to fill a frame in `overlapping_data`.
1260
                            // Extract data from the next buffer.
1261
0
                            overlapping_data
1262
0
                                .extend_from_slice(&next_buffer[..missing_data_for_full_frame]);
1263
0
                            next_buffer.copy_within(missing_data_for_full_frame.., 0);
1264
0
                            next_buffer.truncate(next_buffer.len() - missing_data_for_full_frame);
1265
0
1266
0
                            // Encrypt `overlapping_data` in place and return it.
1267
0
                            chacha20::cipher::StreamCipher::apply_keystream(
1268
0
                                &mut cipher,
1269
0
                                &mut overlapping_data,
1270
0
                            );
1271
0
                            poly1305::universal_hash::UniversalHash::update_padded(
1272
0
                                mac_deref,
1273
0
                                &overlapping_data,
1274
0
                            );
1275
0
                            debug_assert_eq!(overlapping_data.len(), 64);
1276
0
                            total_decrypted_data += 64;
1277
0
                            return Some(mem::take(&mut overlapping_data));
1278
0
                        } else {
1279
0
                            // Not enough data in next buffer to fill `overlapping_data`.
1280
0
                            // Copy the data and continue looping.
1281
0
                            overlapping_data.extend_from_slice(next_buffer);
1282
0
                            let _ = decrypted_buffers.next();
1283
0
                        }
1284
                    } else {
1285
                        // Input is empty. `overlapping_data` is the last buffer.
1286
48
                        chacha20::cipher::StreamCipher::apply_keystream(
1287
48
                            &mut cipher,
1288
48
                            &mut overlapping_data,
1289
48
                        );
1290
48
                        poly1305::universal_hash::UniversalHash::update_padded(
1291
48
                            mac_deref,
1292
48
                            &overlapping_data,
1293
48
                        );
1294
48
                        total_decrypted_data += overlapping_data.len();
1295
48
                        return Some(mem::take(&mut overlapping_data));
1296
                    }
1297
96
                } else if let Some(
mut buffer48
) = decrypted_buffers.next() {
1298
                    // Number of bytes of `next_buffer` that can be encrypted in place.
1299
48
                    let encryptable_in_place = 64 * (buffer.len() / 64);
1300
48
1301
48
                    // Perform the encryption.
1302
48
                    chacha20::cipher::StreamCipher::apply_keystream(
1303
48
                        &mut cipher,
1304
48
                        &mut buffer[..encryptable_in_place],
1305
48
                    );
1306
48
                    poly1305::universal_hash::UniversalHash::update_padded(
1307
48
                        mac_deref,
1308
48
                        &buffer[..encryptable_in_place],
1309
48
                    );
1310
48
1311
48
                    // Copy the non-encryptable-in-place data to `overlapping_data`.
1312
48
                    if encryptable_in_place != buffer.len() {
1313
48
                        overlapping_data.reserve(64);
1314
48
                        overlapping_data.extend_from_slice(&buffer[encryptable_in_place..]);
1315
48
                        buffer.truncate(encryptable_in_place);
1316
48
                    }
0
1317
1318
                    // And return.
1319
48
                    total_decrypted_data += encryptable_in_place;
1320
48
                    return Some(buffer);
1321
                } else {
1322
                    // No more encrypted data to return.
1323
1324
                    // Update the MAC with the length of the associated data and input data.
1325
48
                    let mut block =
1326
48
                        poly1305::universal_hash::generic_array::GenericArray::default();
1327
48
                    block[..8].copy_from_slice(
1328
48
                        &u64::try_from(associated_data_len).unwrap().to_le_bytes(),
1329
48
                    );
1330
48
                    block[8..].copy_from_slice(
1331
48
                        &u64::try_from(total_decrypted_data).unwrap().to_le_bytes(),
1332
48
                    );
1333
48
                    poly1305::universal_hash::UniversalHash::update(mac_deref, &[block]);
1334
48
1335
48
                    // Return the HMAC.
1336
48
                    let mac_bytes =
1337
48
                        poly1305::universal_hash::UniversalHash::finalize(mac.take().unwrap())
1338
48
                            .to_vec();
1339
48
                    return Some(mac_bytes);
1340
                }
1341
            }
1342
192
        }))
Unexecuted instantiation: _RNCINvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_11CipherState24write_chachapoly_messageINtNtNtCsdZExvAaxgia_5alloc3vec5drain5DrainINtB1M_3VechEEE0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCINvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_11CipherState24write_chachapoly_messageINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceINtNtCsdZExvAaxgia_5alloc3vec3VechEEE0Be_
Unexecuted instantiation: _RNCINvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB8_11CipherState24write_chachapoly_messageINtNtNtCsdZExvAaxgia_5alloc3vec5drain5DrainINtB1M_3VechEEE0CsiUjFBJteJ7x_17smoldot_full_node
1343
141
    }
_RINvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB6_11CipherState24write_chachapoly_messageINtNtNtCsdZExvAaxgia_5alloc3vec5drain5DrainINtB1J_3VechEEEBc_
Line
Count
Source
1203
93
    fn write_chachapoly_message(
1204
93
        &'_ mut self,
1205
93
        associated_data: &[u8],
1206
93
        decrypted_buffers: impl Iterator<Item = Vec<u8>>,
1207
93
    ) -> Result<impl Iterator<Item = Vec<u8>>, EncryptError> {
1208
93
        if self.nonce_has_overflowed {
1209
0
            return Err(EncryptError::NonceOverflow);
1210
93
        }
1211
93
1212
93
        let (mut cipher, mac) = self.prepare(associated_data);
1213
93
        let associated_data_len = associated_data.len();
1214
93
1215
93
        // Increment the nonce by 1. This is done ahead of time in order to be sure that the same
1216
93
        // nonce is never re-used even if the API user drops the returned iterator before it ends.
1217
93
        (self.nonce, self.nonce_has_overflowed) = self.nonce.overflowing_add(1);
1218
93
1219
93
        // The difficulty in this function implementation is that the cipher operates on 64 bytes
1220
93
        // blocks (in other words, the data passed to them must have a size multiple of 64), and
1221
93
        // unfortunately the input buffers might be weirdly aligned.
1222
93
        // To overcome this, when there's an alignment issue, we copy the data to a contiguous
1223
93
        // slice.
1224
93
1225
93
        // Each input buffer is encrypted in place as much as possible. Due to alignment issues,
1226
93
        // each input buffer is split in three parts: the data that is appended to the previous
1227
93
        // buffer's data in order to align it, the data that can be encrypted in place, and the
1228
93
        // data that must be prepanded to the start of the next buffer.
1229
93
        // Furthermore, note that the third part of the last buffer can always be encrypted in
1230
93
        // place.
1231
93
1232
93
        // The implementation below requires `decrypted_buffers` to be peekable.
1233
93
        let mut decrypted_buffers = decrypted_buffers.peekable();
1234
93
        // Counter for total input decrypted data increased when iterating over the input.
1235
93
        // Necessary at the very end of the calculation.
1236
93
        let mut total_decrypted_data = 0;
1237
93
        // Data that was copied from the end of the previous buffer.
1238
93
        // TODO: ideally we would avoid copying the end of the previous buffer, and instead only copy the start of the next one, but this means that we couldn't return concrete `Vec`s anymore, and this API change is complicated
1239
93
        let mut overlapping_data = Vec::new();
1240
93
        // `None` if the HMAC has already been returned from the iterator.
1241
93
        let mut mac = Some(mac);
1242
93
1243
93
        // Iterator being returned.
1244
93
        Ok(iter::from_fn(move || {
1245
            loop {
1246
                debug_assert!(overlapping_data.len() < 64);
1247
1248
                // Return if iterator has finished.
1249
                let Some(mac_deref) = mac.as_mut() else {
1250
                    return None;
1251
                };
1252
1253
                if !overlapping_data.is_empty() {
1254
                    // Copy data from the start of the next buffer to the end
1255
                    // of `overlapping_data`.
1256
                    if let Some(next_buffer) = decrypted_buffers.peek_mut() {
1257
                        let missing_data_for_full_frame = 64 - overlapping_data.len();
1258
                        if next_buffer.len() >= missing_data_for_full_frame {
1259
                            // Enough data in next buffer to fill a frame in `overlapping_data`.
1260
                            // Extract data from the next buffer.
1261
                            overlapping_data
1262
                                .extend_from_slice(&next_buffer[..missing_data_for_full_frame]);
1263
                            next_buffer.copy_within(missing_data_for_full_frame.., 0);
1264
                            next_buffer.truncate(next_buffer.len() - missing_data_for_full_frame);
1265
1266
                            // Encrypt `overlapping_data` in place and return it.
1267
                            chacha20::cipher::StreamCipher::apply_keystream(
1268
                                &mut cipher,
1269
                                &mut overlapping_data,
1270
                            );
1271
                            poly1305::universal_hash::UniversalHash::update_padded(
1272
                                mac_deref,
1273
                                &overlapping_data,
1274
                            );
1275
                            debug_assert_eq!(overlapping_data.len(), 64);
1276
                            total_decrypted_data += 64;
1277
                            return Some(mem::take(&mut overlapping_data));
1278
                        } else {
1279
                            // Not enough data in next buffer to fill `overlapping_data`.
1280
                            // Copy the data and continue looping.
1281
                            overlapping_data.extend_from_slice(next_buffer);
1282
                            let _ = decrypted_buffers.next();
1283
                        }
1284
                    } else {
1285
                        // Input is empty. `overlapping_data` is the last buffer.
1286
                        chacha20::cipher::StreamCipher::apply_keystream(
1287
                            &mut cipher,
1288
                            &mut overlapping_data,
1289
                        );
1290
                        poly1305::universal_hash::UniversalHash::update_padded(
1291
                            mac_deref,
1292
                            &overlapping_data,
1293
                        );
1294
                        total_decrypted_data += overlapping_data.len();
1295
                        return Some(mem::take(&mut overlapping_data));
1296
                    }
1297
                } else if let Some(mut buffer) = decrypted_buffers.next() {
1298
                    // Number of bytes of `next_buffer` that can be encrypted in place.
1299
                    let encryptable_in_place = 64 * (buffer.len() / 64);
1300
1301
                    // Perform the encryption.
1302
                    chacha20::cipher::StreamCipher::apply_keystream(
1303
                        &mut cipher,
1304
                        &mut buffer[..encryptable_in_place],
1305
                    );
1306
                    poly1305::universal_hash::UniversalHash::update_padded(
1307
                        mac_deref,
1308
                        &buffer[..encryptable_in_place],
1309
                    );
1310
1311
                    // Copy the non-encryptable-in-place data to `overlapping_data`.
1312
                    if encryptable_in_place != buffer.len() {
1313
                        overlapping_data.reserve(64);
1314
                        overlapping_data.extend_from_slice(&buffer[encryptable_in_place..]);
1315
                        buffer.truncate(encryptable_in_place);
1316
                    }
1317
1318
                    // And return.
1319
                    total_decrypted_data += encryptable_in_place;
1320
                    return Some(buffer);
1321
                } else {
1322
                    // No more encrypted data to return.
1323
1324
                    // Update the MAC with the length of the associated data and input data.
1325
                    let mut block =
1326
                        poly1305::universal_hash::generic_array::GenericArray::default();
1327
                    block[..8].copy_from_slice(
1328
                        &u64::try_from(associated_data_len).unwrap().to_le_bytes(),
1329
                    );
1330
                    block[8..].copy_from_slice(
1331
                        &u64::try_from(total_decrypted_data).unwrap().to_le_bytes(),
1332
                    );
1333
                    poly1305::universal_hash::UniversalHash::update(mac_deref, &[block]);
1334
1335
                    // Return the HMAC.
1336
                    let mac_bytes =
1337
                        poly1305::universal_hash::UniversalHash::finalize(mac.take().unwrap())
1338
                            .to_vec();
1339
                    return Some(mac_bytes);
1340
                }
1341
            }
1342
93
        }))
1343
93
    }
_RINvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB6_11CipherState24write_chachapoly_messageINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceINtNtCsdZExvAaxgia_5alloc3vec3VechEEEBc_
Line
Count
Source
1203
48
    fn write_chachapoly_message(
1204
48
        &'_ mut self,
1205
48
        associated_data: &[u8],
1206
48
        decrypted_buffers: impl Iterator<Item = Vec<u8>>,
1207
48
    ) -> Result<impl Iterator<Item = Vec<u8>>, EncryptError> {
1208
48
        if self.nonce_has_overflowed {
1209
0
            return Err(EncryptError::NonceOverflow);
1210
48
        }
1211
48
1212
48
        let (mut cipher, mac) = self.prepare(associated_data);
1213
48
        let associated_data_len = associated_data.len();
1214
48
1215
48
        // Increment the nonce by 1. This is done ahead of time in order to be sure that the same
1216
48
        // nonce is never re-used even if the API user drops the returned iterator before it ends.
1217
48
        (self.nonce, self.nonce_has_overflowed) = self.nonce.overflowing_add(1);
1218
48
1219
48
        // The difficulty in this function implementation is that the cipher operates on 64 bytes
1220
48
        // blocks (in other words, the data passed to them must have a size multiple of 64), and
1221
48
        // unfortunately the input buffers might be weirdly aligned.
1222
48
        // To overcome this, when there's an alignment issue, we copy the data to a contiguous
1223
48
        // slice.
1224
48
1225
48
        // Each input buffer is encrypted in place as much as possible. Due to alignment issues,
1226
48
        // each input buffer is split in three parts: the data that is appended to the previous
1227
48
        // buffer's data in order to align it, the data that can be encrypted in place, and the
1228
48
        // data that must be prepanded to the start of the next buffer.
1229
48
        // Furthermore, note that the third part of the last buffer can always be encrypted in
1230
48
        // place.
1231
48
1232
48
        // The implementation below requires `decrypted_buffers` to be peekable.
1233
48
        let mut decrypted_buffers = decrypted_buffers.peekable();
1234
48
        // Counter for total input decrypted data increased when iterating over the input.
1235
48
        // Necessary at the very end of the calculation.
1236
48
        let mut total_decrypted_data = 0;
1237
48
        // Data that was copied from the end of the previous buffer.
1238
48
        // TODO: ideally we would avoid copying the end of the previous buffer, and instead only copy the start of the next one, but this means that we couldn't return concrete `Vec`s anymore, and this API change is complicated
1239
48
        let mut overlapping_data = Vec::new();
1240
48
        // `None` if the HMAC has already been returned from the iterator.
1241
48
        let mut mac = Some(mac);
1242
48
1243
48
        // Iterator being returned.
1244
48
        Ok(iter::from_fn(move || {
1245
            loop {
1246
                debug_assert!(overlapping_data.len() < 64);
1247
1248
                // Return if iterator has finished.
1249
                let Some(mac_deref) = mac.as_mut() else {
1250
                    return None;
1251
                };
1252
1253
                if !overlapping_data.is_empty() {
1254
                    // Copy data from the start of the next buffer to the end
1255
                    // of `overlapping_data`.
1256
                    if let Some(next_buffer) = decrypted_buffers.peek_mut() {
1257
                        let missing_data_for_full_frame = 64 - overlapping_data.len();
1258
                        if next_buffer.len() >= missing_data_for_full_frame {
1259
                            // Enough data in next buffer to fill a frame in `overlapping_data`.
1260
                            // Extract data from the next buffer.
1261
                            overlapping_data
1262
                                .extend_from_slice(&next_buffer[..missing_data_for_full_frame]);
1263
                            next_buffer.copy_within(missing_data_for_full_frame.., 0);
1264
                            next_buffer.truncate(next_buffer.len() - missing_data_for_full_frame);
1265
1266
                            // Encrypt `overlapping_data` in place and return it.
1267
                            chacha20::cipher::StreamCipher::apply_keystream(
1268
                                &mut cipher,
1269
                                &mut overlapping_data,
1270
                            );
1271
                            poly1305::universal_hash::UniversalHash::update_padded(
1272
                                mac_deref,
1273
                                &overlapping_data,
1274
                            );
1275
                            debug_assert_eq!(overlapping_data.len(), 64);
1276
                            total_decrypted_data += 64;
1277
                            return Some(mem::take(&mut overlapping_data));
1278
                        } else {
1279
                            // Not enough data in next buffer to fill `overlapping_data`.
1280
                            // Copy the data and continue looping.
1281
                            overlapping_data.extend_from_slice(next_buffer);
1282
                            let _ = decrypted_buffers.next();
1283
                        }
1284
                    } else {
1285
                        // Input is empty. `overlapping_data` is the last buffer.
1286
                        chacha20::cipher::StreamCipher::apply_keystream(
1287
                            &mut cipher,
1288
                            &mut overlapping_data,
1289
                        );
1290
                        poly1305::universal_hash::UniversalHash::update_padded(
1291
                            mac_deref,
1292
                            &overlapping_data,
1293
                        );
1294
                        total_decrypted_data += overlapping_data.len();
1295
                        return Some(mem::take(&mut overlapping_data));
1296
                    }
1297
                } else if let Some(mut buffer) = decrypted_buffers.next() {
1298
                    // Number of bytes of `next_buffer` that can be encrypted in place.
1299
                    let encryptable_in_place = 64 * (buffer.len() / 64);
1300
1301
                    // Perform the encryption.
1302
                    chacha20::cipher::StreamCipher::apply_keystream(
1303
                        &mut cipher,
1304
                        &mut buffer[..encryptable_in_place],
1305
                    );
1306
                    poly1305::universal_hash::UniversalHash::update_padded(
1307
                        mac_deref,
1308
                        &buffer[..encryptable_in_place],
1309
                    );
1310
1311
                    // Copy the non-encryptable-in-place data to `overlapping_data`.
1312
                    if encryptable_in_place != buffer.len() {
1313
                        overlapping_data.reserve(64);
1314
                        overlapping_data.extend_from_slice(&buffer[encryptable_in_place..]);
1315
                        buffer.truncate(encryptable_in_place);
1316
                    }
1317
1318
                    // And return.
1319
                    total_decrypted_data += encryptable_in_place;
1320
                    return Some(buffer);
1321
                } else {
1322
                    // No more encrypted data to return.
1323
1324
                    // Update the MAC with the length of the associated data and input data.
1325
                    let mut block =
1326
                        poly1305::universal_hash::generic_array::GenericArray::default();
1327
                    block[..8].copy_from_slice(
1328
                        &u64::try_from(associated_data_len).unwrap().to_le_bytes(),
1329
                    );
1330
                    block[8..].copy_from_slice(
1331
                        &u64::try_from(total_decrypted_data).unwrap().to_le_bytes(),
1332
                    );
1333
                    poly1305::universal_hash::UniversalHash::update(mac_deref, &[block]);
1334
1335
                    // Return the HMAC.
1336
                    let mac_bytes =
1337
                        poly1305::universal_hash::UniversalHash::finalize(mac.take().unwrap())
1338
                            .to_vec();
1339
                    return Some(mac_bytes);
1340
                }
1341
            }
1342
48
        }))
1343
48
    }
Unexecuted instantiation: _RINvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_11CipherState24write_chachapoly_messageINtNtNtCsdZExvAaxgia_5alloc3vec5drain5DrainINtB1K_3VechEEECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_11CipherState24write_chachapoly_messageINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceINtNtCsdZExvAaxgia_5alloc3vec3VechEEEBc_
Unexecuted instantiation: _RINvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB6_11CipherState24write_chachapoly_messageINtNtNtCsdZExvAaxgia_5alloc3vec5drain5DrainINtB1K_3VechEEECsiUjFBJteJ7x_17smoldot_full_node
1344
1345
    /// Creates a ChaChaPoly1305 frame as a `Vec`.
1346
    ///
1347
    /// Does *not* include the libp2p-specific message length prefix.
1348
48
    fn write_chachapoly_message_to_vec(
1349
48
        &'_ mut self,
1350
48
        associated_data: &[u8],
1351
48
        data: &[u8],
1352
48
    ) -> Result<Vec<u8>, EncryptError> {
1353
48
        Ok(self
1354
48
            .write_chachapoly_message(associated_data, iter::once(data.to_vec()))
?0
1355
144
            .
fold(Vec::new(), 48
|mut a, b| {
1356
144
                if a.is_empty() {
1357
72
                    b
1358
                } else {
1359
72
                    a.extend_from_slice(&b);
1360
72
                    a
1361
                }
1362
144
            }
)48
)
_RNCNvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB7_11CipherState31write_chachapoly_message_to_vec0Bd_
Line
Count
Source
1355
144
            .fold(Vec::new(), |mut a, b| {
1356
144
                if a.is_empty() {
1357
72
                    b
1358
                } else {
1359
72
                    a.extend_from_slice(&b);
1360
72
                    a
1361
                }
1362
144
            }))
Unexecuted instantiation: _RNCNvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB7_11CipherState31write_chachapoly_message_to_vec0Bd_
1363
48
    }
_RNvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_11CipherState31write_chachapoly_message_to_vec
Line
Count
Source
1348
48
    fn write_chachapoly_message_to_vec(
1349
48
        &'_ mut self,
1350
48
        associated_data: &[u8],
1351
48
        data: &[u8],
1352
48
    ) -> Result<Vec<u8>, EncryptError> {
1353
48
        Ok(self
1354
48
            .write_chachapoly_message(associated_data, iter::once(data.to_vec()))
?0
1355
48
            .fold(Vec::new(), |mut a, b| {
1356
                if a.is_empty() {
1357
                    b
1358
                } else {
1359
                    a.extend_from_slice(&b);
1360
                    a
1361
                }
1362
48
            }))
1363
48
    }
Unexecuted instantiation: _RNvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_11CipherState31write_chachapoly_message_to_vec
1364
1365
    /// Highly-specific function when the message to decode is 32 bytes.
1366
24
    fn read_chachapoly_message_to_array(
1367
24
        &'_ mut self,
1368
24
        associated_data: &[u8],
1369
24
        message_data: &[u8; 48],
1370
24
    ) -> Result<[u8; 32], CipherError> {
1371
24
        let mut out = [0; 32];
1372
24
        self.read_chachapoly_message_to_slice(associated_data, message_data, &mut out)
?0
;
1373
24
        Ok(out)
1374
24
    }
_RNvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_11CipherState32read_chachapoly_message_to_array
Line
Count
Source
1366
24
    fn read_chachapoly_message_to_array(
1367
24
        &'_ mut self,
1368
24
        associated_data: &[u8],
1369
24
        message_data: &[u8; 48],
1370
24
    ) -> Result<[u8; 32], CipherError> {
1371
24
        let mut out = [0; 32];
1372
24
        self.read_chachapoly_message_to_slice(associated_data, message_data, &mut out)
?0
;
1373
24
        Ok(out)
1374
24
    }
Unexecuted instantiation: _RNvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_11CipherState32read_chachapoly_message_to_array
1375
1376
24
    fn read_chachapoly_message_to_vec(
1377
24
        &'_ mut self,
1378
24
        associated_data: &[u8],
1379
24
        message_data: &[u8],
1380
24
    ) -> Result<Vec<u8>, CipherError> {
1381
24
        let mut destination = vec![0; message_data.len().saturating_sub(16)];
1382
24
        self.read_chachapoly_message_to_slice(associated_data, message_data, &mut destination)
?0
;
1383
24
        Ok(destination)
1384
24
    }
_RNvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_11CipherState30read_chachapoly_message_to_vec
Line
Count
Source
1376
24
    fn read_chachapoly_message_to_vec(
1377
24
        &'_ mut self,
1378
24
        associated_data: &[u8],
1379
24
        message_data: &[u8],
1380
24
    ) -> Result<Vec<u8>, CipherError> {
1381
24
        let mut destination = vec![0; message_data.len().saturating_sub(16)];
1382
24
        self.read_chachapoly_message_to_slice(associated_data, message_data, &mut destination)
?0
;
1383
24
        Ok(destination)
1384
24
    }
Unexecuted instantiation: _RNvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_11CipherState30read_chachapoly_message_to_vec
1385
1386
91
    fn read_chachapoly_message_to_vec_append(
1387
91
        &'_ mut self,
1388
91
        associated_data: &[u8],
1389
91
        message_data: &[u8],
1390
91
        out: &mut Vec<u8>,
1391
91
    ) -> Result<(), CipherError> {
1392
91
        let len_before = out.len();
1393
91
        out.resize(len_before + message_data.len().saturating_sub(16), 0);
1394
91
        let result = self.read_chachapoly_message_to_slice(
1395
91
            associated_data,
1396
91
            message_data,
1397
91
            &mut out[len_before..],
1398
91
        );
1399
91
        if result.is_err() {
1400
0
            out.truncate(len_before);
1401
91
        }
1402
91
        result
1403
91
    }
_RNvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_11CipherState37read_chachapoly_message_to_vec_append
Line
Count
Source
1386
91
    fn read_chachapoly_message_to_vec_append(
1387
91
        &'_ mut self,
1388
91
        associated_data: &[u8],
1389
91
        message_data: &[u8],
1390
91
        out: &mut Vec<u8>,
1391
91
    ) -> Result<(), CipherError> {
1392
91
        let len_before = out.len();
1393
91
        out.resize(len_before + message_data.len().saturating_sub(16), 0);
1394
91
        let result = self.read_chachapoly_message_to_slice(
1395
91
            associated_data,
1396
91
            message_data,
1397
91
            &mut out[len_before..],
1398
91
        );
1399
91
        if result.is_err() {
1400
0
            out.truncate(len_before);
1401
91
        }
1402
91
        result
1403
91
    }
Unexecuted instantiation: _RNvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_11CipherState37read_chachapoly_message_to_vec_append
1404
1405
139
    fn read_chachapoly_message_to_slice(
1406
139
        &'_ mut self,
1407
139
        associated_data: &[u8],
1408
139
        message_data: &[u8],
1409
139
        destination: &mut [u8],
1410
139
    ) -> Result<(), CipherError> {
1411
139
        debug_assert_eq!(destination.len(), message_data.len() - 16);
1412
1413
139
        if self.nonce_has_overflowed {
1414
0
            return Err(CipherError::NonceOverflow);
1415
139
        }
1416
139
1417
139
        // Messages that are missing a HMAC are invalid.
1418
139
        if message_data.len() < 16 {
1419
0
            return Err(CipherError::MissingHmac);
1420
139
        }
1421
139
1422
139
        let (mut cipher, mut mac) = self.prepare(associated_data);
1423
139
1424
139
        poly1305::universal_hash::UniversalHash::update_padded(
1425
139
            &mut mac,
1426
139
            &message_data[..message_data.len() - 16],
1427
139
        );
1428
139
1429
139
        // Update the MAC with the length of the associated data and input data.
1430
139
        let mut block = poly1305::universal_hash::generic_array::GenericArray::default();
1431
139
        block[..8].copy_from_slice(&u64::try_from(associated_data.len()).unwrap().to_le_bytes());
1432
139
        block[8..].copy_from_slice(
1433
139
            &u64::try_from(message_data.len() - 16)
1434
139
                .unwrap()
1435
139
                .to_le_bytes(),
1436
139
        );
1437
139
        poly1305::universal_hash::UniversalHash::update(&mut mac, &[block]);
1438
139
1439
139
        // Compare the calculated MAC with the one in the payload.
1440
139
        // This is done in constant time.
1441
139
        let obtained_mac_bytes = &message_data[message_data.len() - 16..];
1442
139
        if poly1305::universal_hash::UniversalHash::verify(
1443
139
            mac,
1444
139
            poly1305::universal_hash::generic_array::GenericArray::from_slice(obtained_mac_bytes),
1445
139
        )
1446
139
        .is_err()
1447
        {
1448
0
            return Err(CipherError::HmacInvalid);
1449
139
        }
1450
139
1451
139
        // Only after the MAC has been verified, we copy the data and decrypt it.
1452
139
        // This function returns an error if the cipher stream is exhausted. Because we recreate
1453
139
        // a cipher stream every time we encode a message, and a message is maximum 2^16 bytes,
1454
139
        // this can't happen.
1455
139
        chacha20::cipher::StreamCipher::apply_keystream_b2b(
1456
139
            &mut cipher,
1457
139
            &message_data[..message_data.len() - 16],
1458
139
            destination,
1459
139
        )
1460
139
        .unwrap_or_else(|_| 
unreachable!()0
);
Unexecuted instantiation: _RNCNvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB7_11CipherState32read_chachapoly_message_to_slice0Bd_
Unexecuted instantiation: _RNCNvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB7_11CipherState32read_chachapoly_message_to_slice0Bd_
1461
139
1462
139
        // Increment the nonce by 1.
1463
139
        (self.nonce, self.nonce_has_overflowed) = self.nonce.overflowing_add(1);
1464
139
1465
139
        Ok(())
1466
139
    }
_RNvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_11CipherState32read_chachapoly_message_to_slice
Line
Count
Source
1405
139
    fn read_chachapoly_message_to_slice(
1406
139
        &'_ mut self,
1407
139
        associated_data: &[u8],
1408
139
        message_data: &[u8],
1409
139
        destination: &mut [u8],
1410
139
    ) -> Result<(), CipherError> {
1411
139
        debug_assert_eq!(destination.len(), message_data.len() - 16);
1412
1413
139
        if self.nonce_has_overflowed {
1414
0
            return Err(CipherError::NonceOverflow);
1415
139
        }
1416
139
1417
139
        // Messages that are missing a HMAC are invalid.
1418
139
        if message_data.len() < 16 {
1419
0
            return Err(CipherError::MissingHmac);
1420
139
        }
1421
139
1422
139
        let (mut cipher, mut mac) = self.prepare(associated_data);
1423
139
1424
139
        poly1305::universal_hash::UniversalHash::update_padded(
1425
139
            &mut mac,
1426
139
            &message_data[..message_data.len() - 16],
1427
139
        );
1428
139
1429
139
        // Update the MAC with the length of the associated data and input data.
1430
139
        let mut block = poly1305::universal_hash::generic_array::GenericArray::default();
1431
139
        block[..8].copy_from_slice(&u64::try_from(associated_data.len()).unwrap().to_le_bytes());
1432
139
        block[8..].copy_from_slice(
1433
139
            &u64::try_from(message_data.len() - 16)
1434
139
                .unwrap()
1435
139
                .to_le_bytes(),
1436
139
        );
1437
139
        poly1305::universal_hash::UniversalHash::update(&mut mac, &[block]);
1438
139
1439
139
        // Compare the calculated MAC with the one in the payload.
1440
139
        // This is done in constant time.
1441
139
        let obtained_mac_bytes = &message_data[message_data.len() - 16..];
1442
139
        if poly1305::universal_hash::UniversalHash::verify(
1443
139
            mac,
1444
139
            poly1305::universal_hash::generic_array::GenericArray::from_slice(obtained_mac_bytes),
1445
139
        )
1446
139
        .is_err()
1447
        {
1448
0
            return Err(CipherError::HmacInvalid);
1449
139
        }
1450
139
1451
139
        // Only after the MAC has been verified, we copy the data and decrypt it.
1452
139
        // This function returns an error if the cipher stream is exhausted. Because we recreate
1453
139
        // a cipher stream every time we encode a message, and a message is maximum 2^16 bytes,
1454
139
        // this can't happen.
1455
139
        chacha20::cipher::StreamCipher::apply_keystream_b2b(
1456
139
            &mut cipher,
1457
139
            &message_data[..message_data.len() - 16],
1458
139
            destination,
1459
139
        )
1460
139
        .unwrap_or_else(|_| unreachable!());
1461
139
1462
139
        // Increment the nonce by 1.
1463
139
        (self.nonce, self.nonce_has_overflowed) = self.nonce.overflowing_add(1);
1464
139
1465
139
        Ok(())
1466
139
    }
Unexecuted instantiation: _RNvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_11CipherState32read_chachapoly_message_to_slice
1467
1468
280
    fn prepare(&self, associated_data: &[u8]) -> (chacha20::ChaCha20, poly1305::Poly1305) {
1469
280
        let mut cipher = {
1470
280
            let nonce = {
1471
280
                let mut out = [0; 12];
1472
280
                out[4..].copy_from_slice(&self.nonce.to_le_bytes());
1473
280
                out
1474
280
            };
1475
280
1476
280
            <chacha20::ChaCha20 as chacha20::cipher::KeyIvInit>::new(
1477
280
                chacha20::cipher::generic_array::GenericArray::from_slice(&self.key[..]),
1478
280
                chacha20::cipher::generic_array::GenericArray::from_slice(&nonce[..]),
1479
280
            )
1480
280
        };
1481
280
1482
280
        let mut mac = {
1483
280
            let mut mac_key = zeroize::Zeroizing::new([0u8; 32]);
1484
280
            chacha20::cipher::StreamCipher::apply_keystream(&mut cipher, &mut *mac_key);
1485
280
            chacha20::cipher::StreamCipherSeek::seek(&mut cipher, 64);
1486
280
            <poly1305::Poly1305 as poly1305::universal_hash::KeyInit>::new(
1487
280
                poly1305::universal_hash::generic_array::GenericArray::from_slice(&*mac_key),
1488
280
            )
1489
280
        };
1490
280
1491
280
        poly1305::universal_hash::UniversalHash::update_padded(&mut mac, associated_data);
1492
280
1493
280
        (cipher, mac)
1494
280
    }
_RNvMs8_NtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noiseNtB5_11CipherState7prepare
Line
Count
Source
1468
280
    fn prepare(&self, associated_data: &[u8]) -> (chacha20::ChaCha20, poly1305::Poly1305) {
1469
280
        let mut cipher = {
1470
280
            let nonce = {
1471
280
                let mut out = [0; 12];
1472
280
                out[4..].copy_from_slice(&self.nonce.to_le_bytes());
1473
280
                out
1474
280
            };
1475
280
1476
280
            <chacha20::ChaCha20 as chacha20::cipher::KeyIvInit>::new(
1477
280
                chacha20::cipher::generic_array::GenericArray::from_slice(&self.key[..]),
1478
280
                chacha20::cipher::generic_array::GenericArray::from_slice(&nonce[..]),
1479
280
            )
1480
280
        };
1481
280
1482
280
        let mut mac = {
1483
280
            let mut mac_key = zeroize::Zeroizing::new([0u8; 32]);
1484
280
            chacha20::cipher::StreamCipher::apply_keystream(&mut cipher, &mut *mac_key);
1485
280
            chacha20::cipher::StreamCipherSeek::seek(&mut cipher, 64);
1486
280
            <poly1305::Poly1305 as poly1305::universal_hash::KeyInit>::new(
1487
280
                poly1305::universal_hash::generic_array::GenericArray::from_slice(&*mac_key),
1488
280
            )
1489
280
        };
1490
280
1491
280
        poly1305::universal_hash::UniversalHash::update_padded(&mut mac, associated_data);
1492
280
1493
280
        (cipher, mac)
1494
280
    }
Unexecuted instantiation: _RNvMs8_NtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noiseNtB5_11CipherState7prepare
1495
}
1496
1497
// Implementation of `MixHash`. See <https://noiseprotocol.org/noise.html#the-symmetricstate-object>.
1498
192
fn mix_hash(hash: &mut [u8; 32], data: &[u8]) {
1499
192
    let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1500
192
    sha2::Digest::update(&mut hasher, *hash);
1501
192
    sha2::Digest::update(&mut hasher, data);
1502
192
    sha2::Digest::finalize_into(
1503
192
        hasher,
1504
192
        sha2::digest::generic_array::GenericArray::from_mut_slice(hash),
1505
192
    );
1506
192
}
_RNvNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noise8mix_hash
Line
Count
Source
1498
192
fn mix_hash(hash: &mut [u8; 32], data: &[u8]) {
1499
192
    let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1500
192
    sha2::Digest::update(&mut hasher, *hash);
1501
192
    sha2::Digest::update(&mut hasher, data);
1502
192
    sha2::Digest::finalize_into(
1503
192
        hasher,
1504
192
        sha2::digest::generic_array::GenericArray::from_mut_slice(hash),
1505
192
    );
1506
192
}
Unexecuted instantiation: _RNvNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noise8mix_hash
1507
1508
// Implementation of `HKDF`. See <https://noiseprotocol.org/noise.html#hash-functions>.
1509
//
1510
// Contrary to the version in the Noise specification, this always returns 2 outputs. The third
1511
// output version is never used in this module.
1512
96
fn hkdf(chaining_key: &[u8; 32], input_key_material: &[u8]) -> HkdfOutput {
1513
288
    fn hmac_hash<'a>(
1514
288
        key: &[u8; 32],
1515
288
        data: impl IntoIterator<Item = &'a [u8]>,
1516
288
    ) -> zeroize::Zeroizing<[u8; 32]> {
1517
288
        // Formula is: `H(K XOR opad, H(K XOR ipad, text))`
1518
288
        // See <https://www.ietf.org/rfc/rfc2104.txt>.
1519
288
        let mut ipad = [0x36u8; 64];
1520
288
        let mut opad = [0x5cu8; 64];
1521
96
1522
96
        // Algorithm says that we have to zero-extend `key` to 64 bits, then XOR `ipad` and `opad`
1523
96
        // with that zero-extended `key`. Given that XOR'ing with 0 is a no-op, we don't care with
1524
96
        // that and just XOR the key without zero-extending it.
1525
9.21k
        for n in 0..
key.len()288
{
1526
9.21k
            ipad[n] ^= key[n];
1527
9.21k
            opad[n] ^= key[n];
1528
9.21k
        }
1529
96
1530
288
        let intermediary_result = {
1531
288
            let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1532
288
            sha2::Digest::update(&mut hasher, ipad);
1533
672
            for 
data384
in data {
1534
384
                sha2::Digest::update(&mut hasher, data);
1535
384
            }
1536
288
            sha2::Digest::finalize(hasher)
1537
288
        };
1538
288
1539
288
        let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1540
288
        sha2::Digest::update(&mut hasher, opad);
1541
288
        sha2::Digest::update(&mut hasher, intermediary_result);
1542
288
1543
288
        let mut output = zeroize::Zeroizing::new([0; 32]);
1544
288
        sha2::Digest::finalize_into(
1545
288
            hasher,
1546
288
            sha2::digest::generic_array::GenericArray::from_mut_slice(&mut *output),
1547
288
        );
1548
288
        output
1549
288
    }
_RINvNvNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noise4hkdf9hmac_hashARShj1_EBa_
Line
Count
Source
1513
192
    fn hmac_hash<'a>(
1514
192
        key: &[u8; 32],
1515
192
        data: impl IntoIterator<Item = &'a [u8]>,
1516
192
    ) -> zeroize::Zeroizing<[u8; 32]> {
1517
192
        // Formula is: `H(K XOR opad, H(K XOR ipad, text))`
1518
192
        // See <https://www.ietf.org/rfc/rfc2104.txt>.
1519
192
        let mut ipad = [0x36u8; 64];
1520
192
        let mut opad = [0x5cu8; 64];
1521
1522
        // Algorithm says that we have to zero-extend `key` to 64 bits, then XOR `ipad` and `opad`
1523
        // with that zero-extended `key`. Given that XOR'ing with 0 is a no-op, we don't care with
1524
        // that and just XOR the key without zero-extending it.
1525
6.14k
        for n in 0..
key.len()192
{
1526
6.14k
            ipad[n] ^= key[n];
1527
6.14k
            opad[n] ^= key[n];
1528
6.14k
        }
1529
1530
192
        let intermediary_result = {
1531
192
            let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1532
192
            sha2::Digest::update(&mut hasher, ipad);
1533
384
            for 
data192
in data {
1534
192
                sha2::Digest::update(&mut hasher, data);
1535
192
            }
1536
192
            sha2::Digest::finalize(hasher)
1537
192
        };
1538
192
1539
192
        let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1540
192
        sha2::Digest::update(&mut hasher, opad);
1541
192
        sha2::Digest::update(&mut hasher, intermediary_result);
1542
192
1543
192
        let mut output = zeroize::Zeroizing::new([0; 32]);
1544
192
        sha2::Digest::finalize_into(
1545
192
            hasher,
1546
192
            sha2::digest::generic_array::GenericArray::from_mut_slice(&mut *output),
1547
192
        );
1548
192
        output
1549
192
    }
_RINvNvNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noise4hkdf9hmac_hashARShj2_EBa_
Line
Count
Source
1513
96
    fn hmac_hash<'a>(
1514
96
        key: &[u8; 32],
1515
96
        data: impl IntoIterator<Item = &'a [u8]>,
1516
96
    ) -> zeroize::Zeroizing<[u8; 32]> {
1517
96
        // Formula is: `H(K XOR opad, H(K XOR ipad, text))`
1518
96
        // See <https://www.ietf.org/rfc/rfc2104.txt>.
1519
96
        let mut ipad = [0x36u8; 64];
1520
96
        let mut opad = [0x5cu8; 64];
1521
1522
        // Algorithm says that we have to zero-extend `key` to 64 bits, then XOR `ipad` and `opad`
1523
        // with that zero-extended `key`. Given that XOR'ing with 0 is a no-op, we don't care with
1524
        // that and just XOR the key without zero-extending it.
1525
3.07k
        for n in 0..
key.len()96
{
1526
3.07k
            ipad[n] ^= key[n];
1527
3.07k
            opad[n] ^= key[n];
1528
3.07k
        }
1529
1530
96
        let intermediary_result = {
1531
96
            let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1532
96
            sha2::Digest::update(&mut hasher, ipad);
1533
288
            for 
data192
in data {
1534
192
                sha2::Digest::update(&mut hasher, data);
1535
192
            }
1536
96
            sha2::Digest::finalize(hasher)
1537
96
        };
1538
96
1539
96
        let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1540
96
        sha2::Digest::update(&mut hasher, opad);
1541
96
        sha2::Digest::update(&mut hasher, intermediary_result);
1542
96
1543
96
        let mut output = zeroize::Zeroizing::new([0; 32]);
1544
96
        sha2::Digest::finalize_into(
1545
96
            hasher,
1546
96
            sha2::digest::generic_array::GenericArray::from_mut_slice(&mut *output),
1547
96
        );
1548
96
        output
1549
96
    }
Unexecuted instantiation: _RINvNvNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noise4hkdf9hmac_hashARShj1_EBa_
Unexecuted instantiation: _RINvNvNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noise4hkdf9hmac_hashARShj2_EBa_
1550
96
1551
96
    let temp_key = hmac_hash(chaining_key, [input_key_material]);
1552
96
    let output1 = hmac_hash(&temp_key, [&[0x01][..]]);
1553
96
    let output2 = hmac_hash(&temp_key, [&*output1, &[0x02][..]]);
1554
96
    HkdfOutput { output1, output2 }
1555
96
}
_RNvNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5noise4hkdf
Line
Count
Source
1512
96
fn hkdf(chaining_key: &[u8; 32], input_key_material: &[u8]) -> HkdfOutput {
1513
96
    fn hmac_hash<'a>(
1514
96
        key: &[u8; 32],
1515
96
        data: impl IntoIterator<Item = &'a [u8]>,
1516
96
    ) -> zeroize::Zeroizing<[u8; 32]> {
1517
96
        // Formula is: `H(K XOR opad, H(K XOR ipad, text))`
1518
96
        // See <https://www.ietf.org/rfc/rfc2104.txt>.
1519
96
        let mut ipad = [0x36u8; 64];
1520
96
        let mut opad = [0x5cu8; 64];
1521
96
1522
96
        // Algorithm says that we have to zero-extend `key` to 64 bits, then XOR `ipad` and `opad`
1523
96
        // with that zero-extended `key`. Given that XOR'ing with 0 is a no-op, we don't care with
1524
96
        // that and just XOR the key without zero-extending it.
1525
96
        for n in 0..key.len() {
1526
96
            ipad[n] ^= key[n];
1527
96
            opad[n] ^= key[n];
1528
96
        }
1529
96
1530
96
        let intermediary_result = {
1531
96
            let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1532
96
            sha2::Digest::update(&mut hasher, ipad);
1533
96
            for data in data {
1534
96
                sha2::Digest::update(&mut hasher, data);
1535
96
            }
1536
96
            sha2::Digest::finalize(hasher)
1537
96
        };
1538
96
1539
96
        let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
1540
96
        sha2::Digest::update(&mut hasher, opad);
1541
96
        sha2::Digest::update(&mut hasher, intermediary_result);
1542
96
1543
96
        let mut output = zeroize::Zeroizing::new([0; 32]);
1544
96
        sha2::Digest::finalize_into(
1545
96
            hasher,
1546
96
            sha2::digest::generic_array::GenericArray::from_mut_slice(&mut *output),
1547
96
        );
1548
96
        output
1549
96
    }
1550
96
1551
96
    let temp_key = hmac_hash(chaining_key, [input_key_material]);
1552
96
    let output1 = hmac_hash(&temp_key, [&[0x01][..]]);
1553
96
    let output2 = hmac_hash(&temp_key, [&*output1, &[0x02][..]]);
1554
96
    HkdfOutput { output1, output2 }
1555
96
}
Unexecuted instantiation: _RNvNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5noise4hkdf
1556
1557
/// Output of the [`hkdf`] function.
1558
struct HkdfOutput {
1559
    output1: zeroize::Zeroizing<[u8; 32]>,
1560
    output2: zeroize::Zeroizing<[u8; 32]>,
1561
}
1562
1563
#[cfg(test)]
1564
mod tests {
1565
    use core::{cmp, mem};
1566
1567
    use super::{Config, NoiseHandshake, NoiseKey, ReadWrite};
1568
1569
    #[test]
1570
1
    fn handshake_basic_works() {
1571
4
        fn test_with_buffer_sizes(mut size1: usize, mut size2: usize) {
1572
4
            let key1 = NoiseKey::new(&rand::random(), &rand::random());
1573
4
            let key2 = NoiseKey::new(&rand::random(), &rand::random());
1574
4
1575
4
            let mut handshake1 = NoiseHandshake::new(Config {
1576
4
                key: &key1,
1577
4
                is_initiator: true,
1578
4
                prologue: &[],
1579
4
                ephemeral_secret_key: &rand::random(),
1580
4
            });
1581
4
            let mut handshake2 = NoiseHandshake::new(Config {
1582
4
                key: &key2,
1583
4
                is_initiator: false,
1584
4
                prologue: &[],
1585
4
                ephemeral_secret_key: &rand::random(),
1586
4
            });
1587
4
1588
4
            let mut buf_1_to_2 = Vec::new();
1589
4
            let mut buf_2_to_1 = Vec::new();
1590
1
1591
16
            while !matches!(
1592
20
                (&handshake1, &handshake2),
1593
1
                (
1594
1
                    NoiseHandshake::Success { .. },
1595
1
                    NoiseHandshake::Success { .. }
1596
1
                )
1597
1
            ) {
1598
16
                match handshake1 {
1599
1
                    NoiseHandshake::Success { .. } => 
{}0
1600
16
                    NoiseHandshake::InProgress(nego) => {
1601
16
                        let mut read_write = ReadWrite {
1602
16
                            now: 0,
1603
16
                            incoming_buffer: buf_2_to_1,
1604
16
                            expected_incoming_bytes: Some(0),
1605
16
                            read_bytes: 0,
1606
16
                            write_bytes_queued: buf_1_to_2.len(),
1607
16
                            write_bytes_queueable: Some(size1 - buf_1_to_2.len()),
1608
16
                            write_buffers: vec![mem::take(&mut buf_1_to_2)],
1609
16
                            wake_up_after: None,
1610
16
                        };
1611
16
                        handshake1 = nego.read_write(&mut read_write).unwrap();
1612
16
                        buf_2_to_1 = read_write.incoming_buffer;
1613
16
                        buf_1_to_2.extend(
1614
16
                            read_write
1615
16
                                .write_buffers
1616
16
                                .drain(..)
1617
44
                                .flat_map(|b| b.into_iter()),
1618
16
                        );
1619
16
                        size2 = cmp::max(size2, read_write.expected_incoming_bytes.unwrap_or(0));
1620
16
                    }
1621
1
                }
1622
1
1623
16
                match handshake2 {
1624
1
                    NoiseHandshake::Success { .. } => 
{}0
1625
16
                    NoiseHandshake::InProgress(nego) => {
1626
16
                        let mut read_write = ReadWrite {
1627
16
                            now: 0,
1628
16
                            incoming_buffer: buf_1_to_2,
1629
16
                            expected_incoming_bytes: Some(0),
1630
16
                            read_bytes: 0,
1631
16
                            write_bytes_queued: buf_2_to_1.len(),
1632
16
                            write_bytes_queueable: Some(size2 - buf_2_to_1.len()),
1633
16
                            write_buffers: vec![mem::take(&mut buf_2_to_1)],
1634
16
                            wake_up_after: None,
1635
16
                        };
1636
16
                        handshake2 = nego.read_write(&mut read_write).unwrap();
1637
16
                        buf_1_to_2 = read_write.incoming_buffer;
1638
16
                        buf_2_to_1.extend(
1639
16
                            read_write
1640
16
                                .write_buffers
1641
16
                                .drain(..)
1642
28
                                .flat_map(|b| b.into_iter()),
1643
16
                        );
1644
16
                        size1 = cmp::max(size1, read_write.expected_incoming_bytes.unwrap_or(0));
1645
16
                    }
1646
1
                }
1647
1
            }
1648
4
        }
1649
1
1650
1
        test_with_buffer_sizes(256, 256);
1651
1
        test_with_buffer_sizes(1, 1);
1652
1
        test_with_buffer_sizes(1, 2048);
1653
1
        test_with_buffer_sizes(2048, 1);
1654
1
    }
1655
}