use crate::error::CryptoError;
use super::concat_kdf::{concat_kdf, concat_kdf_1pu, concat_kdf_1pu_legacy};
use super::key_agreement::{EphemeralKeyPair, PrivateKeyAgreement, PublicKeyAgreement};
pub fn derive_key_es(
ephemeral: &PrivateKeyAgreement,
recipient_public: &PublicKeyAgreement,
alg: &[u8],
apu: &[u8],
apv: &[u8],
key_len: u32,
) -> Result<Vec<u8>, CryptoError> {
let z = ephemeral.diffie_hellman(recipient_public)?;
concat_kdf(&z, alg, apu, apv, key_len)
}
pub fn derive_key_es_recipient(
recipient_private: &PrivateKeyAgreement,
ephemeral_public: &PublicKeyAgreement,
alg: &[u8],
apu: &[u8],
apv: &[u8],
key_len: u32,
) -> Result<Vec<u8>, CryptoError> {
let z = recipient_private.diffie_hellman(ephemeral_public)?;
concat_kdf(&z, alg, apu, apv, key_len)
}
pub fn derive_sender_key(
ephemeral: &EphemeralKeyPair,
recipient_public: &PublicKeyAgreement,
apu: &[u8],
apv: &[u8],
) -> Result<[u8; 32], CryptoError> {
let kek = derive_key_es(
&ephemeral.private,
recipient_public,
b"ECDH-ES+A256KW",
apu,
apv,
256,
)?;
kek.try_into()
.map_err(|_| CryptoError::KeyAgreement("derived key wrong size".into()))
}
#[allow(clippy::too_many_arguments)]
pub fn derive_key_1pu(
ephemeral: &PrivateKeyAgreement,
sender_private: &PrivateKeyAgreement,
recipient_public: &PublicKeyAgreement,
alg: &[u8],
apu: &[u8],
apv: &[u8],
cc_tag: &[u8],
key_len: u32,
) -> Result<Vec<u8>, CryptoError> {
let ze = ephemeral.diffie_hellman(recipient_public)?;
let zs = sender_private.diffie_hellman(recipient_public)?;
let mut z = Vec::with_capacity(ze.len() + zs.len());
z.extend_from_slice(&ze);
z.extend_from_slice(&zs);
concat_kdf_1pu(&z, alg, apu, apv, key_len, cc_tag)
}
#[allow(clippy::too_many_arguments)]
pub fn derive_key_1pu_recipient(
recipient_private: &PrivateKeyAgreement,
sender_public: &PublicKeyAgreement,
ephemeral_public: &PublicKeyAgreement,
alg: &[u8],
apu: &[u8],
apv: &[u8],
cc_tag: &[u8],
key_len: u32,
) -> Result<Vec<u8>, CryptoError> {
let ze = recipient_private.diffie_hellman(ephemeral_public)?;
let zs = recipient_private.diffie_hellman(sender_public)?;
let mut z = Vec::with_capacity(ze.len() + zs.len());
z.extend_from_slice(&ze);
z.extend_from_slice(&zs);
concat_kdf_1pu(&z, alg, apu, apv, key_len, cc_tag)
}
#[allow(clippy::too_many_arguments)]
pub fn derive_key_1pu_recipient_legacy(
recipient_private: &PrivateKeyAgreement,
sender_public: &PublicKeyAgreement,
ephemeral_public: &PublicKeyAgreement,
alg: &[u8],
apu: &[u8],
apv: &[u8],
cc_tag: &[u8],
key_len: u32,
) -> Result<Vec<u8>, CryptoError> {
let ze = recipient_private.diffie_hellman(ephemeral_public)?;
let zs = recipient_private.diffie_hellman(sender_public)?;
let mut z = Vec::with_capacity(ze.len() + zs.len());
z.extend_from_slice(&ze);
z.extend_from_slice(&zs);
concat_kdf_1pu_legacy(&z, alg, apu, apv, key_len, cc_tag)
}
pub fn derive_sender_key_1pu(
ephemeral: &EphemeralKeyPair,
sender_private: &PrivateKeyAgreement,
recipient_public: &PublicKeyAgreement,
apu: &[u8],
apv: &[u8],
cc_tag: &[u8],
) -> Result<[u8; 32], CryptoError> {
let kek = derive_key_1pu(
&ephemeral.private,
sender_private,
recipient_public,
b"ECDH-1PU+A256KW",
apu,
apv,
cc_tag,
256,
)?;
kek.try_into()
.map_err(|_| CryptoError::KeyAgreement("derived key wrong size".into()))
}