use crate::utils::Blob;
use crate::{AesKey, Error, ErrorKind, P256KeyPair, P256PublicKey};
use openssl::bn::{BigNum, BigNumContext};
use openssl::ec::PointConversionForm;
use openssl::symm::{self, Cipher, Crypter};
use ring::rand::{SecureRandom, SystemRandom};
use ring::signature;
use {ring, untrusted};
pub fn random_nonce() -> [u8; 12] {
let mut nonce = [0; 12];
SystemRandom::new()
.fill(&mut nonce)
.expect("unable to obtain random bytes");
nonce
}
fn build_iv(nonce: [u8; 12]) -> [u8; 16] {
let mut iv = [0; 16];
iv[0] = 0x02;
iv[1..13].copy_from_slice(&nonce);
iv[13..16].copy_from_slice(&[0x00, 0x00, 0x01]);
debug!("using nonce: {:?}", Blob(&nonce));
debug!("using iv: {:?}", Blob(&iv));
iv
}
pub fn crypt<S: AsRef<[u8]>>(key: AesKey, nonce: [u8; 12], sections: &[S]) -> Vec<Vec<u8>> {
let iv = build_iv(nonce);
let cipher = Cipher::aes_128_ctr();
let block_size = cipher.block_size();
debug!(
"key size: {}, iv size: {:?}, block size: {}",
cipher.key_len(),
cipher.iv_len(),
block_size
);
let mut crypter = Crypter::new(cipher, symm::Mode::Decrypt, key.as_raw(), Some(&iv)).unwrap();
sections
.into_iter()
.map(|section| {
let section = section.as_ref();
let mut data = vec![0; section.len() + block_size];
let size = crypter.update(§ion, &mut data).unwrap();
let data = &data[..size];
assert_eq!(
section.len(),
size,
"input {} bytes, got {} bytes out",
section.len(),
size
);
data.to_vec()
})
.collect()
}
pub fn verify_signature(
pubkey: &P256PublicKey,
signature: &[u8; 64],
data: &[u8],
) -> Result<(), Error> {
let mut bncx = BigNumContext::new().unwrap();
let group = pubkey.inner.group();
let pubkey = pubkey.inner.public_key();
{
let (mut x, mut y) = (BigNum::new().unwrap(), BigNum::new().unwrap());
pubkey
.affine_coordinates_gfp(group, &mut x, &mut y, &mut bncx)
.unwrap();
trace!(
"verify_signature: pubkey (affine_coordinates_gfp): ({},{})",
x.to_hex_str().unwrap(),
y.to_hex_str().unwrap()
);
pubkey
.affine_coordinates_gf2m(group, &mut x, &mut y, &mut bncx)
.unwrap();
trace!(
"verify_signature: pubkey (affine_coordinates_gf2m): ({},{})",
x.to_hex_str().unwrap(),
y.to_hex_str().unwrap()
);
}
let uncompressed_bytes = pubkey
.to_bytes(group, PointConversionForm::UNCOMPRESSED, &mut bncx)
.unwrap();
signature::verify(
&signature::ECDSA_P256_SHA256_FIXED,
untrusted::Input::from(&uncompressed_bytes),
untrusted::Input::from(&data),
untrusted::Input::from(&signature[..]),
)
.map_err(|_| ErrorKind::InvalidSignature)?;
Ok(())
}
pub fn create_signature(keypair: &P256KeyPair, data_to_sign: &[u8]) -> Result<[u8; 64], Error> {
let priv_key = keypair.inner.private_key().to_vec(); let pub_key = keypair
.inner
.public_key()
.to_bytes(
keypair.inner.group(),
PointConversionForm::UNCOMPRESSED,
&mut BigNumContext::new().unwrap(),
)
.unwrap();
let keypair = signature::EcdsaKeyPair::from_private_key_and_public_key(
&signature::ECDSA_P256_SHA256_FIXED_SIGNING,
untrusted::Input::from(&priv_key),
untrusted::Input::from(&pub_key),
)
.map_err(|_| ErrorKind::ParseError)?;
let sig = keypair
.sign(
&ring::rand::SystemRandom::new(),
untrusted::Input::from(data_to_sign),
)
.map_err(|e| Error::with_details(ErrorKind::Other, e.to_string()))?
.as_ref()
.to_vec();
assert_eq!(sig.len(), 64, "expected a 64 byte signature");
if cfg!(debug_assertions) {
signature::verify(
&signature::ECDSA_P256_SHA256_FIXED,
untrusted::Input::from(&pub_key),
untrusted::Input::from(data_to_sign),
untrusted::Input::from(&sig),
)
.expect("created signature could not be verified");
}
let mut raw_sig = [0; 64];
raw_sig.copy_from_slice(&sig);
Ok(raw_sig)
}