Skip to content

Commit

Permalink
EncLS2 PSK client authorization
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Jul 14, 2019
1 parent bbc7a58 commit 54ebfce
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 22 deletions.
89 changes: 86 additions & 3 deletions benches/encls2_client_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use ire::{
dest::DestinationSecretKeys,
ls2::{
enc::{
auth::{ClientInfo, ClientSecretKey, X25519ClientInfo},
auth::{ClientInfo, ClientSecretKey, PSKClientInfo, X25519ClientInfo},
EncLS2Payload, EncryptedLS2,
},
LeaseSet2,
},
},
};
use rand::{thread_rng, RngCore};
use rand::{thread_rng, Rng, RngCore};
use x25519_dalek::{x25519, X25519_BASEPOINT_BYTES};

fn fake_ls2(created: u32, expires: u16) -> LeaseSet2 {
Expand Down Expand Up @@ -104,5 +104,88 @@ fn client_x25519(c: &mut Criterion) {
);
}

criterion_group!(benches, server_x25519, client_x25519);
fn server_psk(c: &mut Criterion) {
let mut rng = thread_rng();
let ls2 = fake_ls2(123_456_789, 2345);

let payload = EncLS2Payload::LS2(ls2);
let credential = b"credential";

let blinded_privkey = SigningPrivateKey::new();
let blinded_pubkey = SigningPublicKey::from_secret(&blinded_privkey).unwrap();

c.bench_function_over_inputs(
"EncLS2_Server_PSK",
move |b, &&count| {
let mut client_info = Vec::with_capacity(count);
for _ in 0..count {
let mut psk = [0; 32];
rng.fill(&mut psk[..]);
client_info.push(PSKClientInfo(psk));
}
let client_info = ClientInfo::PSK(client_info);

b.iter(|| {
EncryptedLS2::encrypt_payload(
&payload,
credential,
blinded_pubkey.clone(),
None,
&blinded_privkey,
Some(client_info.clone()),
)
})
},
&[1, 10, 20, 50, 100],
);
}

fn client_psk(c: &mut Criterion) {
let mut rng = thread_rng();
let ls2 = fake_ls2(123_456_789, 2345);

let payload = EncLS2Payload::LS2(ls2);
let credential = b"credential";

let blinded_privkey = SigningPrivateKey::new();
let blinded_pubkey = SigningPublicKey::from_secret(&blinded_privkey).unwrap();

c.bench_function_over_inputs(
"EncLS2_Client_PSK",
move |b, &&count| {
let mut auth_keys = Vec::with_capacity(count);
let mut client_info = Vec::with_capacity(count);
for _ in 0..count {
let mut psk = [0; 32];
rng.fill(&mut psk[..]);
let mut client_psk = [0; 32];
client_psk.copy_from_slice(&psk[..]);
auth_keys.push(ClientSecretKey::PSK(client_psk));
client_info.push(PSKClientInfo(psk));
}
let client_info = ClientInfo::PSK(client_info);

let enc_ls2 = EncryptedLS2::encrypt_payload(
&payload,
credential,
blinded_pubkey.clone(),
None,
&blinded_privkey,
Some(client_info.clone()),
)
.unwrap();

b.iter(|| enc_ls2.decrypt(credential, Some(&auth_keys.last().unwrap())))
},
&[1, 10, 20, 50, 100],
);
}

criterion_group!(
benches,
server_x25519,
client_x25519,
server_psk,
client_psk
);
criterion_main!(benches);
78 changes: 59 additions & 19 deletions src/data/ls2/enc/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,20 @@ const X25519_AUTH_INFO: &[u8; 8] = b"ELS2_XCA";
#[derive(Clone)]
pub struct X25519ClientInfo(pub [u8; 32]);

#[derive(Clone)]
pub struct PSKClientInfo(pub [u8; 32]);

/// Client information
#[derive(Clone)]
pub enum ClientInfo {
X25519(Vec<X25519ClientInfo>),
PSK(Vec<PSKClientInfo>),
}

// Client's secret authentication key
pub enum ClientSecretKey {
X25519([u8; 32]),
PSK([u8; 32]),
}

/// Per-client authentication data.
Expand All @@ -33,6 +38,7 @@ pub(super) struct ClientAuthData {
#[derive(Debug, PartialEq)]
pub(super) enum ClientAuthType {
X25519([u8; 32], Vec<ClientAuthData>),
PSK([u8; 32], Vec<ClientAuthData>),
}

impl ClientAuthType {
Expand All @@ -43,27 +49,23 @@ impl ClientAuthType {
) -> (Vec<u8>, Option<Self>) {
let mut rng = OsRng::new().unwrap();

match client_info {
Some(ClientInfo::X25519(clients)) => {
macro_rules! base_auth {
($clients:ident, $gen_auth_seed:expr, $gen_secret_value:expr, $salt:expr, $auth_type:ident) => {{
let mut auth_cookie = vec![];
auth_cookie.resize(AUTH_COOKIE_LEN, 0);
rng.fill_bytes(&mut auth_cookie[..]);

let mut esk = [0u8; 32];
rng.fill_bytes(&mut esk[..]);
let epk = x25519(esk, X25519_BASEPOINT_BYTES);
let auth_seed = $gen_auth_seed;

let auth_data = clients
let auth_data = $clients
.into_iter()
.map(|client| {
let shared_secret = x25519(esk, client.0);

let mut okm = [0; S_KEY_LEN + S_IV_LEN + AUTH_ID_LEN];
kdf(
&shared_secret,
&$gen_secret_value(auth_seed, client.0),
subcredential,
created,
&epk,
&$salt(auth_seed),
X25519_AUTH_INFO,
&mut okm,
);
Expand All @@ -86,8 +88,37 @@ impl ClientAuthType {
})
.collect();

(auth_cookie, Some(ClientAuthType::X25519(epk, auth_data)))
}
(
auth_cookie,
Some(ClientAuthType::$auth_type($salt(auth_seed), auth_data)),
)
}};
}

match client_info {
Some(ClientInfo::X25519(clients)) => base_auth!(
clients,
{
let mut esk = [0u8; 32];
rng.fill_bytes(&mut esk[..]);
let epk = x25519(esk, X25519_BASEPOINT_BYTES);
(esk, epk)
},
|(esk, _), client_info| x25519(esk, client_info),
|(_, epk)| epk,
X25519
),
Some(ClientInfo::PSK(clients)) => base_auth!(
clients,
{
let mut auth_salt = [0; 32];
rng.fill_bytes(&mut auth_salt[..]);
auth_salt
},
|_, client_info| client_info,
|auth_salt| auth_salt,
PSK
),
None => (vec![], None),
}
}
Expand All @@ -99,16 +130,14 @@ impl ClientAuthType {
subcredential: &[u8],
created: u32,
) -> Result<Vec<u8>, Error> {
match (self, key) {
(ClientAuthType::X25519(epk, auth_data), ClientSecretKey::X25519(sk)) => {
let shared_secret = x25519(*sk, *epk);

macro_rules! base_auth {
($secret_value:expr, $salt:expr, $auth_data:ident) => {{
let mut okm = [0; S_KEY_LEN + S_IV_LEN + AUTH_ID_LEN];
kdf(
&shared_secret,
$secret_value,
subcredential,
created,
&epk[..],
$salt,
X25519_AUTH_INFO,
&mut okm,
);
Expand All @@ -117,7 +146,7 @@ impl ClientAuthType {
let client_id = &okm[S_KEY_LEN + S_IV_LEN..S_KEY_LEN + S_IV_LEN + AUTH_ID_LEN];

// Scan the list of clients to find ourselves
match auth_data
match $auth_data
.iter()
.filter_map(|data| {
if data.client_id == client_id {
Expand All @@ -140,7 +169,18 @@ impl ClientAuthType {
Some(auth_cookie) => Ok(auth_cookie),
None => Err(Error::NotAuthorised),
}
}};
}

match (self, key) {
(ClientAuthType::X25519(epk, auth_data), ClientSecretKey::X25519(sk)) => {
let shared_secret = x25519(*sk, *epk);
base_auth!(&shared_secret, &epk[..], auth_data)
}
(ClientAuthType::PSK(auth_salt, auth_data), ClientSecretKey::PSK(sk)) => {
base_auth!(&sk[..], &auth_salt[..], auth_data)
}
_ => Err(Error::NotAuthorised),
}
}
}
29 changes: 29 additions & 0 deletions src/data/ls2/enc/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,15 @@ named!(
point.copy_from_slice(epk);
point
}, entries))
) |
1 => do_parse!(
auth_salt: take!(32) >>
entries: length_count!(be_u16, client_auth_data) >>
(ClientAuthType::PSK({
let mut salt = [0; 32];
salt.copy_from_slice(auth_salt);
salt
}, entries))
)
)
)
Expand Down Expand Up @@ -166,6 +175,14 @@ pub(crate) fn gen_enc_ls2_client_auth<'a>(
>> gen_many!(&auth_data, gen_client_auth_data)
>> gen_slice!(client_auth.inner_ciphertext)
),
Some(ClientAuthType::PSK(auth_salt, auth_data)) => do_gen!(
input,
gen_client_auth_flags(&ClientAuthFlags::with_type(1))
>> gen_slice!(&auth_salt)
>> gen_be_u16!(auth_data.len())
>> gen_many!(&auth_data, gen_client_auth_data)
>> gen_slice!(client_auth.inner_ciphertext)
),
}
}

Expand Down Expand Up @@ -317,5 +334,17 @@ mod tests {
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04
][..]
);

eval!(
EncLS2ClientAuth {
auth_data: Some(ClientAuthType::PSK([0xff; 32], vec![])),
inner_ciphertext: vec![1, 2, 3, 4],
},
&[
0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04
][..]
);
}
}

0 comments on commit 54ebfce

Please sign in to comment.