use botan_sys::*;
use utils::*;
use mp::MPI;
use rng::RandomNumberGenerator;
#[derive(Debug)]
pub struct Pubkey {
obj: botan_pubkey_t
}
#[derive(Debug)]
pub struct Privkey {
obj: botan_privkey_t
}
impl Drop for Privkey {
fn drop(&mut self) {
unsafe { botan_privkey_destroy(self.obj) };
}
}
impl Drop for Pubkey {
fn drop(&mut self) {
unsafe { botan_pubkey_destroy(self.obj) };
}
}
impl Privkey {
pub(crate) fn handle(&self) -> botan_privkey_t { self.obj }
pub fn create(alg: &str, params: &str, rng: &RandomNumberGenerator) -> Result<Privkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_privkey_create(&mut obj,
make_cstr(alg)?.as_ptr(),
make_cstr(params)?.as_ptr(),
rng.handle()) }
Ok(Privkey { obj })
}
pub fn load_rsa(p: &MPI, q: &MPI, e: &MPI) -> Result<Privkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_privkey_load_rsa(&mut obj, p.handle(), q.handle(), e.handle()) };
Ok(Privkey { obj })
}
pub fn load_ed25519(key: &[u8]) -> Result<Privkey> {
if key.len() != 32 {
return Err(Error::BadParameter);
}
let mut obj = ptr::null_mut();
call_botan! { botan_privkey_load_ed25519(&mut obj, key.as_ptr()) };
Ok(Privkey { obj })
}
pub fn load_x25519(key: &[u8]) -> Result<Privkey> {
if key.len() != 32 {
return Err(Error::BadParameter);
}
let mut obj = ptr::null_mut();
call_botan! { botan_privkey_load_x25519(&mut obj, key.as_ptr()) };
Ok(Privkey { obj })
}
pub fn load_rsa_pkcs1(pkcs1: &[u8]) -> Result<Privkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_privkey_load_rsa_pkcs1(&mut obj, pkcs1.as_ptr(), pkcs1.len()) }
Ok(Privkey { obj })
}
pub fn load_dh(p: &MPI, g: &MPI, x: &MPI) -> Result<Privkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_privkey_load_dh(&mut obj, p.handle(), g.handle(), x.handle()) };
Ok(Privkey { obj })
}
pub fn load_ecdsa(s: &MPI, curve_name: &str) -> Result<Privkey> {
let mut obj = ptr::null_mut();
let curve_name = make_cstr(curve_name)?;
call_botan! { botan_privkey_load_ecdsa(&mut obj, s.handle(), curve_name.as_ptr()) }
Ok(Privkey { obj })
}
pub fn load_ecdh(s: &MPI, curve_name: &str) -> Result<Privkey> {
let mut obj = ptr::null_mut();
let curve_name = make_cstr(curve_name)?;
call_botan! { botan_privkey_load_ecdh(&mut obj, s.handle(), curve_name.as_ptr()) }
Ok(Privkey { obj })
}
pub fn load_der(der: &[u8]) -> Result<Privkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_privkey_load(&mut obj, ptr::null_mut(), der.as_ptr(), der.len(), ptr::null()) }
Ok(Privkey { obj })
}
pub fn load_pem(pem: &str) -> Result<Privkey> {
let mut obj = ptr::null_mut();
let cpem = make_cstr(pem)?;
call_botan! { botan_privkey_load(&mut obj, ptr::null_mut(), cpem.as_ptr() as *const u8, pem.len(), ptr::null()) }
Ok(Privkey { obj })
}
pub fn load_encrypted_der(der: &[u8], passphrase: &str) -> Result<Privkey> {
let mut obj = ptr::null_mut();
let passphrase = make_cstr(passphrase)?;
call_botan! { botan_privkey_load(&mut obj, ptr::null_mut(), der.as_ptr(), der.len(), passphrase.as_ptr()) }
Ok(Privkey { obj })
}
pub fn load_encrypted_pem(pem: &str, passphrase: &str) -> Result<Privkey> {
let mut obj = ptr::null_mut();
let passphrase = make_cstr(passphrase)?;
let cpem = make_cstr(pem)?;
call_botan! { botan_privkey_load(&mut obj, ptr::null_mut(), cpem.as_ptr() as *const u8, pem.len(), passphrase.as_ptr()) }
Ok(Privkey { obj })
}
pub fn check_key(&self, rng: &RandomNumberGenerator) -> Result<bool> {
let flags = 1u32;
let rc = unsafe { botan_privkey_check_key(self.obj, rng.handle(), flags) };
if rc == 0 {
Ok(true)
}
else if rc == -1 {
Ok(false)
}
else {
Err(Error::from(rc))
}
}
pub fn pubkey(&self) -> Result<Pubkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_privkey_export_pubkey(&mut obj, self.obj) }
Ok(Pubkey { obj })
}
pub fn algo_name(&self) -> Result<String> {
let name_len = 32;
call_botan_ffi_returning_string(name_len, &|out_buf, out_len| {
unsafe { botan_privkey_algo_name(self.obj, out_buf as *mut c_char, out_len) }
})
}
pub fn der_encode(&self) -> Result<Vec<u8>> {
let der_len = 4096; call_botan_ffi_returning_vec_u8(der_len, &|out_buf, out_len| {
unsafe { botan_privkey_export(self.obj, out_buf, out_len, 0u32) }
})
}
pub fn der_encode_encrypted(&self, passphrase: &str, rng: &RandomNumberGenerator) -> Result<Vec<u8>> {
self.der_encode_encrypted_with_options(passphrase, "AES-256/CBC", "SHA-512", 150000, rng)
}
pub fn der_encode_encrypted_with_options(&self,
passphrase: &str,
cipher: &str,
pbkdf: &str,
pbkdf_iter: usize,
rng: &RandomNumberGenerator) -> Result<Vec<u8>> {
let der_len = 4096; let passphrase = make_cstr(passphrase)?;
let cipher = make_cstr(cipher)?;
let pbkdf = make_cstr(pbkdf)?;
call_botan_ffi_returning_vec_u8(der_len, &|out_buf, out_len| {
unsafe {
botan_privkey_export_encrypted_pbkdf_iter(
self.obj, out_buf, out_len, rng.handle(),
passphrase.as_ptr(),
pbkdf_iter,
cipher.as_ptr(),
pbkdf.as_ptr(),
0u32)
}
})
}
pub fn pem_encode_encrypted(&self, passphrase: &str, rng: &RandomNumberGenerator) -> Result<String> {
self.pem_encode_encrypted_with_options(passphrase, "AES-256/CBC", "SHA-512", 150000, rng)
}
pub fn pem_encode_encrypted_with_options(&self,
passphrase: &str,
cipher: &str,
pbkdf: &str,
pbkdf_iter: usize,
rng: &RandomNumberGenerator) -> Result<String> {
let pem_len = 4096;
let passphrase = make_cstr(passphrase)?;
let cipher = make_cstr(cipher)?;
let pbkdf = make_cstr(pbkdf)?;
call_botan_ffi_returning_string(pem_len, &|out_buf, out_len| {
unsafe {
botan_privkey_export_encrypted_pbkdf_iter(
self.obj, out_buf, out_len, rng.handle(),
passphrase.as_ptr(),
pbkdf_iter,
cipher.as_ptr(),
pbkdf.as_ptr(),
1u32)
}
})
}
pub fn pem_encode(&self) -> Result<String> {
let pem_len = 4096; call_botan_ffi_returning_string(pem_len, &|out_buf, out_len| {
unsafe { botan_privkey_export(self.obj, out_buf, out_len, 1u32) }
})
}
pub fn key_agreement_key(&self) -> Result<Vec<u8>> {
let ka_key_len = 512; call_botan_ffi_returning_vec_u8(ka_key_len, &|out_buf, out_len| {
unsafe { botan_pk_op_key_agreement_export_public(self.obj, out_buf, out_len) }
})
}
pub fn get_field(&self, which: &str) -> Result<MPI> {
let which = make_cstr(which)?;
let r = MPI::new()?;
call_botan! { botan_privkey_get_field(r.handle(), self.obj, which.as_ptr()) };
Ok(r)
}
pub fn get_ed25519_key(&self) -> Result<(Vec<u8>, Vec<u8>)> {
let mut out = vec![0; 64];
call_botan! {
botan_privkey_ed25519_get_privkey(self.obj, out.as_mut_ptr())
}
let pubkey = out.split_off(32);
Ok((pubkey,out))
}
pub fn get_x25519_key(&self) -> Result<Vec<u8>> {
let mut out = vec![0; 32];
call_botan! {
botan_privkey_x25519_get_privkey(self.obj, out.as_mut_ptr())
}
Ok(out)
}
}
impl Pubkey {
pub(crate) fn from_handle(obj: botan_pubkey_t) -> Pubkey { Pubkey { obj } }
pub(crate) fn handle(&self) -> botan_pubkey_t { self.obj }
pub fn load_der(der: &[u8]) -> Result<Pubkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_pubkey_load(&mut obj, der.as_ptr(), der.len()) }
Ok(Pubkey { obj })
}
pub fn load_pem(pem: &str) -> Result<Pubkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_pubkey_load(&mut obj, make_cstr(pem)?.as_ptr() as *const u8, pem.len()) }
Ok(Pubkey { obj })
}
pub fn load_rsa(n: &MPI, e: &MPI) -> Result<Pubkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_pubkey_load_rsa(&mut obj, n.handle(), e.handle()) };
Ok(Pubkey { obj })
}
pub fn load_dh(p: &MPI, g: &MPI, y: &MPI) -> Result<Pubkey> {
let mut obj = ptr::null_mut();
call_botan! { botan_pubkey_load_dh(&mut obj, p.handle(), g.handle(), y.handle()) };
Ok(Pubkey { obj })
}
pub fn load_ecdsa(pub_x: &MPI, pub_y: &MPI, curve_name: &str) -> Result<Pubkey> {
let mut obj = ptr::null_mut();
let curve_name = make_cstr(curve_name)?;
call_botan! { botan_pubkey_load_ecdsa(&mut obj, pub_x.handle(), pub_y.handle(), curve_name.as_ptr()) }
Ok(Pubkey { obj })
}
pub fn load_ecdh(pub_x: &MPI, pub_y: &MPI, curve_name: &str) -> Result<Pubkey> {
let mut obj = ptr::null_mut();
let curve_name = make_cstr(curve_name)?;
call_botan! { botan_pubkey_load_ecdh(&mut obj, pub_x.handle(), pub_y.handle(), curve_name.as_ptr()) }
Ok(Pubkey { obj })
}
pub fn load_ed25519(key: &[u8]) -> Result<Pubkey> {
if key.len() != 32 {
return Err(Error::BadParameter);
}
let mut obj = ptr::null_mut();
call_botan! { botan_pubkey_load_ed25519(&mut obj, key.as_ptr()) };
Ok(Pubkey { obj })
}
pub fn load_x25519(key: &[u8]) -> Result<Pubkey> {
if key.len() != 32 {
return Err(Error::BadParameter);
}
let mut obj = ptr::null_mut();
call_botan! { botan_pubkey_load_x25519(&mut obj, key.as_ptr()) };
Ok(Pubkey { obj })
}
pub fn estimated_strength(&self) -> Result<usize> {
let mut strength = 0;
call_botan! { botan_pubkey_estimated_strength(self.obj, &mut strength) };
Ok(strength)
}
pub fn check_key(&self, rng: &RandomNumberGenerator) -> Result<bool> {
let flags = 1u32;
let rc = unsafe { botan_pubkey_check_key(self.obj, rng.handle(), flags) };
if rc == 0 {
Ok(true)
}
else if rc == -1 {
Ok(false)
}
else {
Err(Error::from(rc))
}
}
pub fn fingerprint(&self, hash: &str) -> Result<String> {
let hash = make_cstr(hash)?;
let fprint_len = 64; call_botan_ffi_returning_string(fprint_len, &|out_buf, out_len| {
unsafe { botan_pubkey_fingerprint(self.obj, hash.as_ptr(), out_buf, out_len) }
})
}
pub fn der_encode(&self) -> Result<Vec<u8>> {
let der_len = 4096; call_botan_ffi_returning_vec_u8(der_len, &|out_buf, out_len| {
unsafe { botan_pubkey_export(self.obj, out_buf, out_len, 0u32) }
})
}
pub fn pem_encode(&self) -> Result<String> {
let pem_len = 4096; call_botan_ffi_returning_string(pem_len, &|out_buf, out_len| {
unsafe { botan_pubkey_export(self.obj, out_buf, out_len, 1u32) }
})
}
pub fn algo_name(&self) -> Result<String> {
let name_len = 32;
call_botan_ffi_returning_string(name_len, &|out_buf, out_len| {
unsafe { botan_pubkey_algo_name(self.obj, out_buf as *mut c_char, out_len) }
})
}
pub fn get_field(&self, which: &str) -> Result<MPI> {
let which = make_cstr(which)?;
let r = MPI::new()?;
call_botan! { botan_pubkey_get_field(r.handle(), self.obj, which.as_ptr()) };
Ok(r)
}
pub fn get_ed25519_key(&self) -> Result<Vec<u8>> {
let mut out = vec![0; 32];
call_botan! {
botan_pubkey_ed25519_get_pubkey(self.obj, out.as_mut_ptr())
}
Ok(out)
}
pub fn get_x25519_key(&self) -> Result<Vec<u8>> {
let mut out = vec![0; 32];
call_botan! {
botan_pubkey_x25519_get_pubkey(self.obj, out.as_mut_ptr())
}
Ok(out)
}
}
pub fn pkcs_hash_id(hash_algo: &str) -> Result<Vec<u8>> {
let hash_algo = make_cstr(hash_algo)?;
let id_len = 32; call_botan_ffi_returning_vec_u8(id_len, &|out_buf, out_len| {
unsafe { botan_pkcs_hash_id(hash_algo.as_ptr(), out_buf, out_len) }
})
}