use crate::{kem::*, params::*, symmetric::kdf, KyberLibError};
use rand_core::{CryptoRng, RngCore};
pub const UAKE_INIT_BYTES: usize =
KYBER_PUBLIC_KEY_BYTES + KYBER_CIPHERTEXT_BYTES;
pub const UAKE_RESPONSE_BYTES: usize = KYBER_CIPHERTEXT_BYTES;
pub const AKE_INIT_BYTES: usize =
KYBER_PUBLIC_KEY_BYTES + KYBER_CIPHERTEXT_BYTES;
pub const AKE_RESPONSE_BYTES: usize = 2 * KYBER_CIPHERTEXT_BYTES;
pub type Encapsulated = Result<
(
[u8; KYBER_CIPHERTEXT_BYTES],
[u8; KYBER_SHARED_SECRET_BYTES],
),
KyberLibError,
>;
pub type Decapsulated =
Result<[u8; KYBER_SHARED_SECRET_BYTES], KyberLibError>;
pub type PublicKey = [u8; KYBER_PUBLIC_KEY_BYTES];
pub type SecretKey = [u8; KYBER_SECRET_KEY_BYTES];
pub type SharedSecret = [u8; KYBER_SHARED_SECRET_BYTES];
pub type UakeSendInit = [u8; UAKE_INIT_BYTES];
pub type UakeSendResponse = [u8; UAKE_RESPONSE_BYTES];
pub type AkeSendInit = [u8; AKE_INIT_BYTES];
pub type AkeSendResponse = [u8; AKE_RESPONSE_BYTES];
type TempKey = [u8; KYBER_SHARED_SECRET_BYTES];
type Eska = [u8; KYBER_SECRET_KEY_BYTES];
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Uake {
pub shared_secret: SharedSecret,
pub send_a: UakeSendInit,
pub send_b: UakeSendResponse,
pub temp_key: TempKey,
pub eska: Eska,
}
impl Default for Uake {
fn default() -> Self {
Uake {
shared_secret: [0u8; KYBER_SHARED_SECRET_BYTES],
send_a: [0u8; UAKE_INIT_BYTES],
send_b: [0u8; UAKE_RESPONSE_BYTES],
temp_key: [0u8; KYBER_SHARED_SECRET_BYTES],
eska: [0u8; KYBER_SECRET_KEY_BYTES],
}
}
}
impl Uake {
pub fn new() -> Self {
Self::default()
}
pub fn client_init<R>(
&mut self,
pubkey: &PublicKey,
rng: &mut R,
) -> Result<UakeSendInit, KyberLibError>
where
R: CryptoRng + RngCore,
{
uake_init_a(
&mut self.send_a,
&mut self.temp_key,
&mut self.eska,
pubkey,
rng,
)?;
Ok(self.send_a)
}
pub fn server_receive<R>(
&mut self,
send_a: UakeSendInit,
secretkey: &SecretKey,
rng: &mut R,
) -> Result<UakeSendResponse, KyberLibError>
where
R: CryptoRng + RngCore,
{
uake_shared_b(
&mut self.send_b,
&mut self.shared_secret,
&send_a,
secretkey,
rng,
)?;
Ok(self.send_b)
}
pub fn client_confirm(
&mut self,
send_b: UakeSendResponse,
) -> Result<(), KyberLibError> {
uake_shared_a(
&mut self.shared_secret,
&send_b,
&self.temp_key,
&self.eska,
)?;
Ok(())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Ake {
pub shared_secret: SharedSecret,
pub send_a: AkeSendInit,
pub send_b: AkeSendResponse,
pub temp_key: TempKey,
pub eska: Eska,
}
impl Default for Ake {
fn default() -> Self {
Ake {
shared_secret: [0u8; KYBER_SHARED_SECRET_BYTES],
send_a: [0u8; AKE_INIT_BYTES],
send_b: [0u8; AKE_RESPONSE_BYTES],
temp_key: [0u8; KYBER_SHARED_SECRET_BYTES],
eska: [0u8; KYBER_SECRET_KEY_BYTES],
}
}
}
impl Ake {
pub fn new() -> Self {
Self::default()
}
pub fn client_init<R>(
&mut self,
pubkey: &PublicKey,
rng: &mut R,
) -> Result<AkeSendInit, KyberLibError>
where
R: CryptoRng + RngCore,
{
ake_init_a(
&mut self.send_a,
&mut self.temp_key,
&mut self.eska,
pubkey,
rng,
)?;
Ok(self.send_a)
}
pub fn server_receive<R>(
&mut self,
ake_send_a: AkeSendInit,
pubkey: &PublicKey,
secretkey: &SecretKey,
rng: &mut R,
) -> Result<AkeSendResponse, KyberLibError>
where
R: CryptoRng + RngCore,
{
ake_shared_b(
&mut self.send_b,
&mut self.shared_secret,
&ake_send_a,
secretkey,
pubkey,
rng,
)?;
Ok(self.send_b)
}
pub fn client_confirm(
&mut self,
send_b: AkeSendResponse,
secretkey: &SecretKey,
) -> Result<(), KyberLibError> {
ake_shared_a(
&mut self.shared_secret,
&send_b,
&self.temp_key,
&self.eska,
secretkey,
)?;
Ok(())
}
}
fn uake_init_a<R>(
send: &mut [u8],
tk: &mut [u8],
sk: &mut [u8],
pkb: &[u8],
rng: &mut R,
) -> Result<(), KyberLibError>
where
R: CryptoRng + RngCore,
{
generate_key_pair(send, sk, rng, None)?;
encrypt_message(
&mut send[KYBER_PUBLIC_KEY_BYTES..],
tk,
pkb,
rng,
None,
)?;
Ok(())
}
fn uake_shared_b<R>(
send: &mut [u8],
k: &mut [u8],
recv: &[u8],
skb: &[u8],
rng: &mut R,
) -> Result<(), KyberLibError>
where
R: CryptoRng + RngCore,
{
let mut buf = [0u8; 2 * KYBER_SYM_BYTES];
encrypt_message(send, &mut buf, recv, rng, None)?;
decrypt_message(
&mut buf[KYBER_SYM_BYTES..],
&recv[KYBER_PUBLIC_KEY_BYTES..],
skb,
);
kdf(k, &buf, 2 * KYBER_SYM_BYTES);
Ok(())
}
fn uake_shared_a(
k: &mut [u8],
recv: &[u8],
tk: &[u8],
sk: &[u8],
) -> Result<(), KyberLibError> {
let mut buf = [0u8; 2 * KYBER_SYM_BYTES];
decrypt_message(&mut buf, recv, sk);
buf[KYBER_SYM_BYTES..].copy_from_slice(tk);
kdf(k, &buf, 2 * KYBER_SYM_BYTES);
Ok(())
}
fn ake_init_a<R>(
send: &mut [u8],
tk: &mut [u8],
sk: &mut [u8],
pkb: &[u8],
rng: &mut R,
) -> Result<(), KyberLibError>
where
R: CryptoRng + RngCore,
{
generate_key_pair(send, sk, rng, None)?;
encrypt_message(
&mut send[KYBER_PUBLIC_KEY_BYTES..],
tk,
pkb,
rng,
None,
)?;
Ok(())
}
fn ake_shared_b<R>(
send: &mut [u8],
k: &mut [u8],
recv: &[u8],
skb: &[u8],
pka: &[u8],
rng: &mut R,
) -> Result<(), KyberLibError>
where
R: CryptoRng + RngCore,
{
let mut buf = [0u8; 3 * KYBER_SYM_BYTES];
encrypt_message(send, &mut buf, recv, rng, None)?;
encrypt_message(
&mut send[KYBER_CIPHERTEXT_BYTES..],
&mut buf[KYBER_SYM_BYTES..],
pka,
rng,
None,
)?;
decrypt_message(
&mut buf[2 * KYBER_SYM_BYTES..],
&recv[KYBER_PUBLIC_KEY_BYTES..],
skb,
);
kdf(k, &buf, 3 * KYBER_SYM_BYTES);
Ok(())
}
fn ake_shared_a(
k: &mut [u8],
recv: &[u8],
tk: &[u8],
sk: &[u8],
ska: &[u8],
) -> Result<(), KyberLibError> {
let mut buf = [0u8; 3 * KYBER_SYM_BYTES];
decrypt_message(&mut buf, recv, sk);
decrypt_message(
&mut buf[KYBER_SYM_BYTES..],
&recv[KYBER_CIPHERTEXT_BYTES..],
ska,
);
buf[2 * KYBER_SYM_BYTES..].copy_from_slice(tk);
kdf(k, &buf, 3 * KYBER_SYM_BYTES);
Ok(())
}