1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use crate::bytes::{as_mut, as_ref};
use crate::crypto::{keys::*, message::*, outcome::*, shared_secret::*};
use crate::error::HandshakeError;
use crate::util::send;
use core::mem::size_of;
use futures_io::{AsyncRead, AsyncWrite};
use futures_util::io::{AsyncReadExt, AsyncWriteExt};
use ssb_crypto::{ephemeral::generate_ephemeral_keypair, Keypair, NetworkKey};
use std::io;
pub async fn server_side<S>(
mut stream: S,
net_key: &NetworkKey,
keypair: &Keypair,
) -> Result<HandshakeKeys, HandshakeError<io::Error>>
where
S: AsyncRead + AsyncWrite + Unpin,
{
let r = try_server_side(&mut stream, net_key, keypair).await;
if r.is_err() {
stream.close().await.unwrap_or(());
}
r
}
async fn try_server_side<S>(
mut stream: S,
net_key: &NetworkKey,
keypair: &Keypair,
) -> Result<HandshakeKeys, HandshakeError<io::Error>>
where
S: AsyncRead + AsyncWrite + Unpin,
{
use HandshakeError::*;
let (eph_pk, eph_sk) = {
let (p, s) = generate_ephemeral_keypair();
(ServerEphPublicKey(p), ServerEphSecretKey(s))
};
let client_eph_pk = {
let mut buf = [0; size_of::<ClientHello>()];
stream.read_exact(&mut buf).await?;
as_ref::<ClientHello>(&buf)
.verify(&net_key)
.ok_or(ClientHelloVerifyFailed)?
};
send(&mut stream, ServerHello::new(&eph_pk, &net_key)).await?;
let shared_a = SharedA::server_side(&eph_sk, &client_eph_pk).ok_or(SharedAInvalid)?;
let shared_b = SharedB::server_side(&keypair, &client_eph_pk).ok_or(SharedBInvalid)?;
let (client_sig, client_pk) = {
let mut buf = [0u8; 112];
stream.read_exact(&mut buf).await?;
as_mut::<ClientAuth>(&mut buf)
.verify(&keypair, &net_key, &shared_a, &shared_b)
.ok_or(ClientAuthVerifyFailed)?
};
let shared_c = SharedC::server_side(&eph_sk, &client_pk).ok_or(SharedCInvalid)?;
send(
&mut stream,
ServerAccept::new(
&keypair,
&client_pk,
&net_key,
&client_sig,
&shared_a,
&shared_b,
&shared_c,
),
)
.await?;
Ok(HandshakeKeys {
read_key: client_to_server_key(
&ServerPublicKey(keypair.public),
&net_key,
&shared_a,
&shared_b,
&shared_c,
),
read_starting_nonce: starting_nonce(&net_key, &eph_pk.0),
write_key: server_to_client_key(&client_pk, &net_key, &shared_a, &shared_b, &shared_c),
write_starting_nonce: starting_nonce(&net_key, &client_eph_pk.0),
peer_key: client_pk.0,
})
}