use std::ptr;
use bindings::{themis_gen_ec_key_pair, themis_gen_rsa_key_pair};
use crate::error::{Error, ErrorKind, Result};
use crate::keys::{
EcdsaKeyPair, EcdsaPrivateKey, EcdsaPublicKey, RsaKeyPair, RsaPrivateKey, RsaPublicKey,
};
pub fn gen_rsa_key_pair() -> RsaKeyPair {
match try_gen_rsa_key_pair() {
Ok(keys) => keys,
Err(e) => panic!("themis_gen_rsa_key_pair() failed: {}", e),
}
}
fn try_gen_rsa_key_pair() -> Result<RsaKeyPair> {
let mut private_key = Vec::new();
let mut public_key = Vec::new();
let mut private_key_len = 0;
let mut public_key_len = 0;
unsafe {
let status = themis_gen_rsa_key_pair(
ptr::null_mut(),
&mut private_key_len,
ptr::null_mut(),
&mut public_key_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
private_key.reserve(private_key_len);
public_key.reserve(public_key_len);
unsafe {
let status = themis_gen_rsa_key_pair(
private_key.as_mut_ptr(),
&mut private_key_len,
public_key.as_mut_ptr(),
&mut public_key_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(private_key_len <= private_key.capacity());
debug_assert!(public_key_len <= public_key.capacity());
private_key.set_len(private_key_len as usize);
public_key.set_len(public_key_len as usize);
}
let private_key = RsaPrivateKey::from_vec(private_key);
let public_key = RsaPublicKey::from_vec(public_key);
Ok(RsaKeyPair::join(private_key, public_key))
}
pub fn gen_ec_key_pair() -> EcdsaKeyPair {
match try_gen_ec_key_pair() {
Ok(keys) => keys,
Err(e) => panic!("themis_gen_ec_key_pair() failed: {}", e),
}
}
fn try_gen_ec_key_pair() -> Result<EcdsaKeyPair> {
let mut private_key = Vec::new();
let mut public_key = Vec::new();
let mut private_key_len = 0;
let mut public_key_len = 0;
unsafe {
let status = themis_gen_ec_key_pair(
ptr::null_mut(),
&mut private_key_len,
ptr::null_mut(),
&mut public_key_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
private_key.reserve(private_key_len);
public_key.reserve(public_key_len);
unsafe {
let status = themis_gen_ec_key_pair(
private_key.as_mut_ptr(),
&mut private_key_len,
public_key.as_mut_ptr(),
&mut public_key_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(private_key_len <= private_key.capacity());
debug_assert!(public_key_len <= public_key.capacity());
private_key.set_len(private_key_len as usize);
public_key.set_len(public_key_len as usize);
}
let private_key = EcdsaPrivateKey::from_vec(private_key);
let public_key = EcdsaPublicKey::from_vec(public_key);
Ok(EcdsaKeyPair::join(private_key, public_key))
}