Skip to main content

ssb_handshake/
client.rs

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