use crate::{KeyAgreement, SecioError};
use futures::{future, prelude::*};
use log::debug;
use ring::agreement as ring_agreement;
use ring::rand as ring_rand;
use untrusted::Input as UntrustedInput;
impl Into<&'static ring_agreement::Algorithm> for KeyAgreement {
#[inline]
fn into(self) -> &'static ring_agreement::Algorithm {
match self {
KeyAgreement::EcdhP256 => &ring_agreement::ECDH_P256,
KeyAgreement::EcdhP384 => &ring_agreement::ECDH_P384,
}
}
}
pub type AgreementPrivateKey = ring_agreement::EphemeralPrivateKey;
pub fn generate_agreement(algorithm: KeyAgreement) -> impl Future<Item = (AgreementPrivateKey, Vec<u8>), Error = SecioError> {
let rng = ring_rand::SystemRandom::new();
match ring_agreement::EphemeralPrivateKey::generate(algorithm.into(), &rng) {
Ok(tmp_priv_key) => {
let r = tmp_priv_key.compute_public_key()
.map_err(|_| SecioError::EphemeralKeyGenerationFailed)
.map(move |tmp_pub_key| (tmp_priv_key, tmp_pub_key.as_ref().to_vec()));
future::result(r)
},
Err(_) => {
debug!("failed to generate ECDH key");
future::err(SecioError::EphemeralKeyGenerationFailed)
},
}
}
pub fn agree(algorithm: KeyAgreement, my_private_key: AgreementPrivateKey, other_public_key: &[u8], _out_size: usize)
-> impl Future<Item = Vec<u8>, Error = SecioError>
{
ring_agreement::agree_ephemeral(my_private_key, algorithm.into(),
UntrustedInput::from(other_public_key),
SecioError::SecretGenerationFailed,
|key_material| Ok(key_material.to_vec()))
.into_future()
}