use mbedtls_sys::ECDSA_MAX_LEN as MBEDTLS_ECDSA_MAX_LEN;
use mbedtls_sys::*;
use crate::error::{codes, IntoResult, Result};
define!(
#[c_ty(ecp_group_id)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum EcGroupId {
None = ECP_DP_NONE,
SecP192R1 = ECP_DP_SECP192R1,
SecP224R1 = ECP_DP_SECP224R1,
SecP256R1 = ECP_DP_SECP256R1,
SecP384R1 = ECP_DP_SECP384R1,
SecP521R1 = ECP_DP_SECP521R1,
Bp256R1 = ECP_DP_BP256R1,
Bp384R1 = ECP_DP_BP384R1,
Bp512R1 = ECP_DP_BP512R1,
Curve25519 = ECP_DP_CURVE25519,
SecP192K1 = ECP_DP_SECP192K1,
SecP224K1 = ECP_DP_SECP224K1,
SecP256K1 = ECP_DP_SECP256K1,
Curve448 = ECP_DP_CURVE448,
}
);
impl From<ecp_group_id> for EcGroupId {
fn from(inner: ecp_group_id) -> EcGroupId {
match inner {
ECP_DP_NONE => EcGroupId::None,
ECP_DP_SECP192R1 => EcGroupId::SecP192R1,
ECP_DP_SECP224R1 => EcGroupId::SecP224R1,
ECP_DP_SECP256R1 => EcGroupId::SecP256R1,
ECP_DP_SECP384R1 => EcGroupId::SecP384R1,
ECP_DP_SECP521R1 => EcGroupId::SecP521R1,
ECP_DP_BP256R1 => EcGroupId::Bp256R1,
ECP_DP_BP384R1 => EcGroupId::Bp384R1,
ECP_DP_BP512R1 => EcGroupId::Bp512R1,
ECP_DP_CURVE25519 => EcGroupId::Curve25519,
ECP_DP_SECP192K1 => EcGroupId::SecP192K1,
ECP_DP_SECP224K1 => EcGroupId::SecP224K1,
ECP_DP_SECP256K1 => EcGroupId::SecP256K1,
ECP_DP_CURVE448 => EcGroupId::Curve448,
_ => panic!("Invalid EC group ID"),
}
}
}
pub const ECDSA_MAX_LEN: usize = MBEDTLS_ECDSA_MAX_LEN as usize;
define!(
#[c_ty(ecp_keypair)]
#[repr(C)]
struct EcpKeypair;
const init: fn() -> Self = ecp_keypair_init;
const drop: fn(&mut Self) = ecp_keypair_free;
impl<'a> Into<ptr> {}
impl<'a> UnsafeFrom<ptr> {}
);
define!(
#[c_ty(ecdh_context)]
#[repr(C)]
struct Ecdh;
const init: fn() -> Self = ecdh_init;
const drop: fn(&mut Self) = ecdh_free;
impl<'a> Into<ptr> {}
);
impl Ecdh {
pub fn from_keys(private: &EcpKeypair, public: &EcpKeypair) -> Result<Ecdh> {
if public.inner.grp.id == ECP_DP_NONE || public.inner.grp.id != private.inner.grp.id {
return Err(codes::EcpBadInputData.into());
}
let mut ret = Self::init();
unsafe {
ecp_group_copy(&mut ret.inner.grp, &private.inner.grp).into_result()?;
mpi_copy(&mut ret.inner.d, &private.inner.d).into_result()?;
ecp_copy(&mut ret.inner.Qp, &public.inner.Q).into_result()?;
}
Ok(ret)
}
pub fn calc_secret<F: crate::rng::Random>(&mut self, shared: &mut [u8], rng: &mut F) -> Result<usize> {
let mut olen = 0;
unsafe {
ecdh_calc_secret(
&mut self.inner,
&mut olen,
shared.as_mut_ptr(),
shared.len(),
Some(F::call),
rng.data_ptr(),
)
.into_result()?
};
Ok(olen)
}
}
#[cfg(test)]
mod tests {
use crate::pk::Pk;
#[test]
fn p192_dh() {
const PRIVATE_P192: &'static [u8] = b"-----BEGIN PRIVATE KEY-----
MG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBjxfT/qNnt000CFHKQn
DcskwnH0Rb7Z1SehNAMyAASxUFNAH1coVjfsMkwc0hOeOmfeNzkjSzfyacFYY3SC
qtZEzWkt0dPvLIp8SeOJ9/Y=
-----END PRIVATE KEY-----\0";
const PUBLIC_P192: &'static [u8] = b"-----BEGIN PUBLIC KEY-----
MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEQupt2Zad0qYf6hqsf46Y7cyJbG5V
hXzA375dfGH6yIsRgRveMo6KDRK/AanSBLUj
-----END PUBLIC KEY-----\0";
const DH_P192: &'static [u8] = &[
0x80, 0x3d, 0x8a, 0xb2, 0xe5, 0xb6, 0xe6, 0xfc, 0xa7, 0x15, 0x73, 0x7c, 0x3a, 0x82, 0xf7, 0xce, 0x3c, 0x78, 0x31,
0x24, 0xf6, 0xd5, 0x1c, 0xd0,
];
let mut k_pr = Pk::from_private_key(PRIVATE_P192, None).unwrap();
let k_pb = Pk::from_public_key(PUBLIC_P192).unwrap();
let mut out = [0; 192 / 8];
let len = k_pr
.agree(&k_pb, &mut out, &mut crate::test_support::rand::test_rng())
.unwrap();
assert_eq!(len, DH_P192.len());
assert_eq!(out, DH_P192);
}
}