use rand_core::{RngCore, CryptoRng};
use crate::{
kem::*,
symmetric::kdf,
params::*,
KyberError
};
pub const UAKE_INIT_BYTES: usize = KYBER_PUBLICKEYBYTES + KYBER_CIPHERTEXTBYTES;
pub const UAKE_RESPONSE_BYTES: usize = KYBER_CIPHERTEXTBYTES;
pub const AKE_INIT_BYTES: usize = KYBER_PUBLICKEYBYTES + KYBER_CIPHERTEXTBYTES;
pub const AKE_RESPONSE_BYTES: usize = 2 * KYBER_CIPHERTEXTBYTES;
pub type Encapsulated = Result<([u8; KYBER_CIPHERTEXTBYTES], [u8; KYBER_SSBYTES]), KyberError>;
pub type Decapsulated = Result<[u8; KYBER_SSBYTES], KyberError>;
pub type PublicKey = [u8; KYBER_PUBLICKEYBYTES];
pub type SecretKey = [u8; KYBER_SECRETKEYBYTES];
pub type SharedSecret = [u8; KYBER_SSBYTES];
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_SSBYTES];
type Eska = [u8; KYBER_SECRETKEYBYTES];
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Uake {
pub shared_secret: SharedSecret,
send_a: UakeSendInit,
send_b: UakeSendResponse,
temp_key: TempKey,
eska: Eska
}
impl Default for Uake {
fn default() -> Self {
Uake {
shared_secret: [0u8; KYBER_SSBYTES],
send_a: [0u8; UAKE_INIT_BYTES],
send_b: [0u8; UAKE_RESPONSE_BYTES],
temp_key: [0u8; KYBER_SSBYTES],
eska: [0u8; KYBER_SECRETKEYBYTES],
}
}
}
impl Uake {
pub fn new() -> Self {
Self::default()
}
pub fn client_init<R>(&mut self, pubkey: &PublicKey, rng: &mut R)
-> UakeSendInit
where R: CryptoRng + RngCore
{
uake_init_a(
&mut self.send_a, &mut self.temp_key,
&mut self.eska, pubkey, rng
);
self.send_a
}
pub fn server_receive<R>(
&mut self, send_a: UakeSendInit, secretkey: &SecretKey, rng: &mut R
)
-> Result<UakeSendResponse, KyberError>
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<(), KyberError>
{
uake_shared_a(
&mut self.shared_secret, &send_b,
&self.temp_key, &self.eska
)?;
Ok(())
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Ake {
pub shared_secret: SharedSecret,
send_a: AkeSendInit,
send_b: AkeSendResponse,
temp_key: TempKey,
eska: Eska
}
impl Default for Ake {
fn default() -> Self {
Ake {
shared_secret: [0u8; KYBER_SSBYTES],
send_a: [0u8; AKE_INIT_BYTES],
send_b: [0u8; AKE_RESPONSE_BYTES],
temp_key: [0u8; KYBER_SSBYTES],
eska: [0u8; KYBER_SECRETKEYBYTES],
}
}
}
impl Ake {
pub fn new() -> Self {
Self::default()
}
pub fn client_init<R>(&mut self, pubkey: &PublicKey, rng: &mut R)
-> AkeSendInit
where R: CryptoRng + RngCore
{
ake_init_a(
&mut self.send_a, &mut self.temp_key,
&mut self.eska, pubkey, rng
);
self.send_a
}
pub fn server_receive<R>(
&mut self, ake_send_a: AkeSendInit, pubkey: &PublicKey,
secretkey: &SecretKey, rng: &mut R
)
-> Result<AkeSendResponse, KyberError>
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<(), KyberError>
{
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
)
where R: CryptoRng + RngCore
{
crypto_kem_keypair(send, sk, rng, None);
crypto_kem_enc(&mut send[KYBER_PUBLICKEYBYTES..], tk, pkb, rng, None);
}
fn uake_shared_b<R>(
send: &mut[u8],
k: &mut[u8],
recv: &[u8],
skb: &[u8],
rng: &mut R
) -> Result<(), KyberError>
where R: CryptoRng + RngCore
{
let mut buf = [0u8; 2*KYBER_SYMBYTES];
crypto_kem_enc(send, &mut buf, recv, rng, None);
crypto_kem_dec(&mut buf[KYBER_SYMBYTES..], &recv[KYBER_PUBLICKEYBYTES..], skb)?;
kdf(k, &buf, 2*KYBER_SYMBYTES);
Ok(())
}
fn uake_shared_a(
k: &mut[u8],
recv: &[u8],
tk: &[u8],
sk: &[u8]
) -> Result<(), KyberError>
{
let mut buf = [0u8; 2*KYBER_SYMBYTES];
crypto_kem_dec(&mut buf, recv, sk)?;
buf[KYBER_SYMBYTES..].copy_from_slice(&tk[..]);
kdf(k, &buf, 2*KYBER_SYMBYTES);
Ok(())
}
fn ake_init_a<R>(
send: &mut[u8],
tk: &mut[u8],
sk: &mut[u8],
pkb: &[u8],
rng: &mut R
)
where R: CryptoRng + RngCore
{
crypto_kem_keypair(send, sk, rng, None);
crypto_kem_enc(&mut send[KYBER_PUBLICKEYBYTES..], tk, pkb, rng, None);
}
fn ake_shared_b<R>(
send: &mut[u8],
k: &mut[u8],
recv: &[u8],
skb: &[u8],
pka: &[u8],
rng: &mut R
) -> Result<(), KyberError>
where R: CryptoRng + RngCore
{
let mut buf = [0u8; 3*KYBER_SYMBYTES];
crypto_kem_enc(send, &mut buf, recv, rng, None);
crypto_kem_enc(&mut send[KYBER_CIPHERTEXTBYTES..], &mut buf[KYBER_SYMBYTES..], pka, rng, None);
crypto_kem_dec(&mut buf[2*KYBER_SYMBYTES..], &recv[KYBER_PUBLICKEYBYTES..], skb)?;
kdf(k, &buf, 3*KYBER_SYMBYTES);
Ok(())
}
fn ake_shared_a(
k: &mut[u8],
recv: &[u8],
tk: &[u8],
sk: &[u8],
ska: &[u8]
) -> Result<(), KyberError>
{
let mut buf = [0u8; 3*KYBER_SYMBYTES];
crypto_kem_dec(&mut buf, recv, sk)?;
crypto_kem_dec(&mut buf[KYBER_SYMBYTES..], &recv[KYBER_CIPHERTEXTBYTES..], ska)?;
buf[2*KYBER_SYMBYTES..].copy_from_slice(&tk[..]);
kdf(k, &buf, 3*KYBER_SYMBYTES);
Ok(())
}