use crate::common::{concat, ct_eq};
use crate::opaque::config::OpaqueConfig;
use crate::opaque::config::NN;
use crate::opaque::internal::{opaque_ake, opaque_credentials};
use crate::opaque::model::*;
pub struct OpaqueServer<'a> {
server_private_key: Vec<u8>,
server_public_key: Vec<u8>,
oprf_seed: Vec<u8>,
config: &'a OpaqueConfig,
}
impl<'a> OpaqueServer<'a> {
pub fn new(
server_private_key: Vec<u8>,
server_public_key: Vec<u8>,
oprf_seed: Vec<u8>,
config: &'a OpaqueConfig,
) -> Self {
Self {
server_private_key,
server_public_key,
oprf_seed,
config,
}
}
pub fn generate(config: &'a OpaqueConfig, rng: &mut dyn rand_core::CryptoRngCore) -> Self {
let sk = config.cipher_suite().oprf_suite().random_scalar(rng);
let pk = config
.cipher_suite()
.oprf_suite()
.group_spec()
.scalar_multiply_generator(&sk);
let mut seed = vec![0u8; config.nok()];
rng.fill_bytes(&mut seed);
Self {
server_private_key: sk,
server_public_key: pk,
oprf_seed: seed,
config,
}
}
pub fn server_public_key(&self) -> &[u8] {
&self.server_public_key
}
pub fn server_private_key(&self) -> &[u8] {
&self.server_private_key
}
pub fn oprf_seed(&self) -> &[u8] {
&self.oprf_seed
}
pub fn create_registration_response(
&self,
request: &RegistrationRequest,
credential_identifier: &[u8],
) -> Result<RegistrationResponse, &'static str> {
opaque_credentials::create_registration_response(
self.config,
request,
&self.server_public_key,
credential_identifier,
&self.oprf_seed,
)
}
pub fn generate_ke2(
&self,
server_identity: Option<&[u8]>,
record: &RegistrationRecord,
credential_identifier: &[u8],
ke1: &KE1,
client_identity: Option<&[u8]>,
rng: &mut dyn rand_core::CryptoRngCore,
) -> Result<ServerKE2Result, &'static str> {
opaque_ake::generate_ke2(
self.config,
server_identity,
&self.server_private_key,
&self.server_public_key,
record,
credential_identifier,
&self.oprf_seed,
ke1,
client_identity,
rng,
)
}
pub fn server_finish(
&self,
state: &ServerAuthState,
ke3: &KE3,
) -> Result<Vec<u8>, &'static str> {
if !ct_eq(&state.expected_client_mac, &ke3.client_mac) {
return Err("Authentication failed");
}
Ok(state.session_key.clone())
}
pub fn generate_fake_ke2(
&self,
ke1: &KE1,
credential_identifier: &[u8],
server_identity: Option<&[u8]>,
client_identity: Option<&[u8]>,
rng: &mut dyn rand_core::CryptoRngCore,
) -> Result<ServerKE2Result, &'static str> {
let fake_record = self.create_fake_record(credential_identifier);
opaque_ake::generate_ke2(
self.config,
server_identity,
&self.server_private_key,
&self.server_public_key,
&fake_record,
credential_identifier,
&self.oprf_seed,
ke1,
client_identity,
rng,
)
}
fn create_fake_record(&self, credential_identifier: &[u8]) -> RegistrationRecord {
let suite = self.config.cipher_suite();
let fake_client_sk_seed = suite.hkdf_expand(
&self.oprf_seed,
&concat(&[credential_identifier, b"FakeClientKey"]),
self.config.nsk(),
);
let fake_kp = suite.derive_ake_key_pair(&fake_client_sk_seed);
let fake_client_pk = fake_kp.public_key;
let fake_masking_key = suite.hkdf_expand(
&self.oprf_seed,
&concat(&[credential_identifier, b"FakeMaskingKey"]),
self.config.nh(),
);
let fake_envelope = Envelope {
envelope_nonce: vec![0u8; NN],
auth_tag: vec![0u8; self.config.nm()],
};
RegistrationRecord {
client_public_key: fake_client_pk,
masking_key: fake_masking_key,
envelope: fake_envelope,
}
}
#[allow(clippy::too_many_arguments)]
pub fn generate_ke2_deterministic(
&self,
server_identity: Option<&[u8]>,
record: &RegistrationRecord,
credential_identifier: &[u8],
ke1: &KE1,
client_identity: Option<&[u8]>,
masking_nonce: &[u8],
server_ake_key_seed: &[u8],
server_nonce: &[u8],
) -> Result<ServerKE2Result, &'static str> {
opaque_ake::generate_ke2_deterministic(
self.config,
server_identity,
&self.server_private_key,
&self.server_public_key,
record,
credential_identifier,
&self.oprf_seed,
ke1,
client_identity,
masking_nonce,
server_ake_key_seed,
server_nonce,
)
}
}