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;

/// Perform the server side of the handshake using the given `AsyncRead + AsyncWrite` stream.
/// Closes the stream on handshake failure.
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))
    };

    // Receive and verify client hello
    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 server hello
    send(&mut stream, ServerHello::new(&eph_pk, &net_key)).await?;

    // Derive shared secrets
    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)?;

    // Receive and verify client auth
    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)?
    };

    // Derive shared secret
    let shared_c = SharedC::server_side(&eph_sk, &client_pk).ok_or(SharedCInvalid)?;

    // Send server accept
    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,
    })
}