key/aziot-keys/src/key_pair.rs (773 lines of code) (raw):
// Copyright (c) Microsoft. All rights reserved.
pub(crate) unsafe extern "C" fn create_key_pair_if_not_exists(
id: *const std::os::raw::c_char,
preferred_algorithms: *const std::os::raw::c_char,
) -> crate::AZIOT_KEYS_RC {
crate::r#catch(|| {
let id = {
if id.is_null() {
return Err(crate::implementation::err_invalid_parameter(
"id",
"expected non-NULL",
));
}
let id = std::ffi::CStr::from_ptr(id);
let id = id
.to_str()
.map_err(|err| crate::implementation::err_invalid_parameter("id", err))?;
id
};
let preferred_algorithms =
PreferredAlgorithm::from_str(preferred_algorithms).map_err(|err| {
crate::implementation::err_invalid_parameter("preferred_algorithms", err)
})?;
let locations = crate::implementation::Location::of(id)?;
if load_inner(&locations, true)?.is_none() {
create_inner(&locations, &preferred_algorithms)?;
if load_inner(&locations, false)?.is_none() {
return Err(crate::implementation::err_external(
"key created successfully but could not be found",
));
}
}
Ok(())
})
}
pub(crate) unsafe extern "C" fn move_key_pair(
from: *const std::os::raw::c_char,
to: *const std::os::raw::c_char,
) -> crate::AZIOT_KEYS_RC {
crate::r#catch(|| {
let from = {
if from.is_null() {
return Err(crate::implementation::err_invalid_parameter(
"from",
"expected non-NULL",
));
}
let from = std::ffi::CStr::from_ptr(from);
let from = from
.to_str()
.map_err(|err| crate::implementation::err_invalid_parameter("from", err))?;
crate::implementation::Location::of(from)?
};
let to = {
if to.is_null() {
return Err(crate::implementation::err_invalid_parameter(
"to",
"expected non-NULL",
));
}
let to = std::ffi::CStr::from_ptr(to);
let to = to
.to_str()
.map_err(|err| crate::implementation::err_invalid_parameter("to", err))?;
crate::implementation::Location::of(to)?
};
move_inner(&from, &to)
})
}
pub(crate) unsafe extern "C" fn load_key_pair(
id: *const std::os::raw::c_char,
) -> crate::AZIOT_KEYS_RC {
crate::r#catch(|| {
let id = {
if id.is_null() {
return Err(crate::implementation::err_invalid_parameter(
"id",
"expected non-NULL",
));
}
let id = std::ffi::CStr::from_ptr(id);
let id = id
.to_str()
.map_err(|err| crate::implementation::err_invalid_parameter("id", err))?;
id
};
let locations = crate::implementation::Location::of(id)?;
if load_inner(&locations, false)?.is_none() {
return Err(crate::implementation::err_invalid_parameter(
"id",
"not found",
));
}
Ok(())
})
}
pub(crate) unsafe extern "C" fn get_key_pair_parameter(
id: *const std::os::raw::c_char,
r#type: crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_TYPE,
value: *mut std::os::raw::c_uchar,
value_len: *mut usize,
) -> crate::AZIOT_KEYS_RC {
crate::r#catch(|| {
let id = {
if id.is_null() {
return Err(crate::implementation::err_invalid_parameter(
"id",
"expected non-NULL",
));
}
let id = std::ffi::CStr::from_ptr(id);
let id = id
.to_str()
.map_err(|err| crate::implementation::err_invalid_parameter("id", err))?;
id
};
let mut value_len_out = std::ptr::NonNull::new(value_len).ok_or_else(|| {
crate::implementation::err_invalid_parameter("value_len", "expected non-NULL")
})?;
let locations = crate::implementation::Location::of(id)?;
let key_pair = load_inner(&locations, false)?
.ok_or_else(|| crate::implementation::err_invalid_parameter("id", "not found"))?;
match r#type {
crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_TYPE_ALGORITHM => {
let expected_value_len =
std::mem::size_of::<crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_ALGORITHM>();
let actual_value_len = *value_len_out.as_ref();
*value_len_out.as_mut() = expected_value_len;
if !value.is_null() {
if actual_value_len < expected_value_len {
return Err(crate::implementation::err_invalid_parameter(
"value",
"insufficient size",
));
}
let value_out = std::slice::from_raw_parts_mut(value, actual_value_len);
let value = match key_pair {
KeyPair::FileSystem(public_key, _) => {
if public_key.ec_key().is_ok() {
crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_ALGORITHM_EC
} else if public_key.rsa().is_ok() {
crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_ALGORITHM_RSA
} else {
return Err(crate::implementation::err_invalid_parameter(
"id",
"key is neither RSA nor EC",
));
}
}
KeyPair::Pkcs11(pkcs11::KeyPair::Ec(_, _)) => {
crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_ALGORITHM_EC
}
KeyPair::Pkcs11(pkcs11::KeyPair::Rsa(_, _)) => {
crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_ALGORITHM_RSA
}
};
let value = value.inner.to_ne_bytes();
value_out[..expected_value_len].copy_from_slice(&value[..]);
}
Ok(())
}
crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_TYPE_EC_CURVE_OID => {
let ec_key = key_pair.ec_key()?;
let curve_nid = ec_key.group().curve_name().ok_or_else(|| {
crate::implementation::err_invalid_parameter(
"type",
"key does not have named curve",
)
})?;
let curve = openssl2::EcCurve::from_nid(curve_nid).ok_or_else(|| {
crate::implementation::err_invalid_parameter("type", "key curve not recognized")
})?;
let curve_oid = curve.as_oid_der();
let expected_value_len = curve_oid.len();
let actual_value_len = *value_len_out.as_ref();
*value_len_out.as_mut() = expected_value_len;
if !value.is_null() {
if actual_value_len < expected_value_len {
return Err(crate::implementation::err_invalid_parameter(
"value",
"insufficient size",
));
}
let value_out = std::slice::from_raw_parts_mut(value, actual_value_len);
value_out[..expected_value_len].copy_from_slice(curve_oid);
}
Ok(())
}
crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_TYPE_EC_POINT => {
let ec_key = key_pair.ec_key()?;
let curve = ec_key.group();
let point = ec_key.public_key();
let mut big_num_context = openssl::bn::BigNumContext::new()?;
let point = point.to_bytes(
curve,
openssl::ec::PointConversionForm::COMPRESSED,
&mut big_num_context,
)?;
let expected_value_len = point.len();
let actual_value_len = *value_len_out.as_ref();
*value_len_out.as_mut() = expected_value_len;
if !value.is_null() {
if actual_value_len < expected_value_len {
return Err(crate::implementation::err_invalid_parameter(
"value",
"insufficient size",
));
}
let value_out = std::slice::from_raw_parts_mut(value, actual_value_len);
value_out[..expected_value_len].copy_from_slice(&point);
}
Ok(())
}
crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_TYPE_RSA_MODULUS => {
let rsa = key_pair.rsa()?;
let modulus = rsa.n().to_vec();
let expected_value_len = modulus.len();
let actual_value_len = *value_len_out.as_ref();
*value_len_out.as_mut() = expected_value_len;
if !value.is_null() {
if actual_value_len < expected_value_len {
return Err(crate::implementation::err_invalid_parameter(
"value",
"insufficient size",
));
}
let value_out = std::slice::from_raw_parts_mut(value, actual_value_len);
value_out[..expected_value_len].copy_from_slice(&modulus);
}
Ok(())
}
crate::AZIOT_KEYS_KEY_PAIR_PARAMETER_TYPE_RSA_EXPONENT => {
let rsa = key_pair.rsa()?;
let exponent = rsa.e().to_vec();
let expected_value_len = exponent.len();
let actual_value_len = *value_len_out.as_ref();
*value_len_out.as_mut() = expected_value_len;
if !value.is_null() {
if actual_value_len < expected_value_len {
return Err(crate::implementation::err_invalid_parameter(
"value",
"insufficient size",
));
}
let value_out = std::slice::from_raw_parts_mut(value, actual_value_len);
value_out[..expected_value_len].copy_from_slice(&exponent);
}
Ok(())
}
_ => Err(crate::implementation::err_invalid_parameter(
"type",
"unrecognized value",
)),
}
})
}
pub(crate) unsafe extern "C" fn delete_key_pair(
id: *const std::os::raw::c_char,
) -> crate::AZIOT_KEYS_RC {
crate::r#catch(|| {
let id = {
if id.is_null() {
return Err(crate::implementation::err_invalid_parameter(
"id",
"expected non-NULL",
));
}
let id = std::ffi::CStr::from_ptr(id);
let id = id
.to_str()
.map_err(|err| crate::implementation::err_invalid_parameter("id", err))?;
id
};
let locations = crate::implementation::Location::of(id)?;
delete_inner(&locations)?;
Ok(())
})
}
pub(crate) unsafe fn sign(
locations: &[crate::implementation::Location],
mechanism: crate::AZIOT_KEYS_SIGN_MECHANISM,
_parameters: *const std::ffi::c_void,
digest: &[u8],
) -> Result<(usize, Vec<u8>), crate::AZIOT_KEYS_RC> {
let key_pair = load_inner(locations, false)?
.ok_or_else(|| crate::implementation::err_invalid_parameter("id", "not found"))?;
let result = match key_pair {
KeyPair::FileSystem(_, private_key) => {
match (mechanism, private_key.ec_key(), private_key.rsa()) {
(crate::AZIOT_KEYS_SIGN_MECHANISM_ECDSA, Ok(ec_key), _) => {
let signature_len = {
let ec_key = foreign_types_shared::ForeignType::as_ptr(&ec_key);
let signature_len = openssl_sys2::ECDSA_size(ec_key);
let signature_len = signature_len.try_into().map_err(|err| {
crate::implementation::err_external(format!(
"ECDSA_size returned invalid value: {err}"
))
})?;
signature_len
};
let signature = openssl::ecdsa::EcdsaSig::sign(digest, &ec_key)?;
let signature = signature.to_der()?;
Some((signature_len, signature))
}
_ => None,
}
}
KeyPair::Pkcs11(key_pair) => match (mechanism, key_pair) {
(
crate::AZIOT_KEYS_SIGN_MECHANISM_ECDSA,
pkcs11::KeyPair::Ec(public_key, private_key),
) => {
let signature_len = {
let ec_key = public_key.parameters().map_err(|err| {
crate::implementation::err_external(format!(
"could not get key pair parameters: {err}"
))
})?;
let ec_key = foreign_types_shared::ForeignType::as_ptr(&ec_key);
let signature_len = openssl_sys2::ECDSA_size(ec_key);
let signature_len = signature_len.try_into().map_err(|err| {
crate::implementation::err_external(format!(
"ECDSA_size returned invalid value: {err}"
))
})?;
signature_len
};
let signature = {
let mut signature = vec![0_u8; signature_len];
let signature_len =
private_key.sign(digest, &mut signature).map_err(|err| {
crate::implementation::err_external(format!("could not sign: {err}"))
})?;
let signature_len: usize = signature_len.try_into().expect("CK_ULONG -> usize");
let r = openssl::bn::BigNum::from_slice(&signature[..(signature_len / 2)])?;
let s = openssl::bn::BigNum::from_slice(
&signature[(signature_len / 2)..signature_len],
)?;
let signature = openssl::ecdsa::EcdsaSig::from_private_components(r, s)?;
let signature = signature.to_der()?;
signature
};
Some((signature_len, signature))
}
_ => None,
},
};
let result = result.ok_or_else(|| {
crate::implementation::err_invalid_parameter("mechanism", "unrecognized value")
})?;
Ok(result)
}
pub(crate) unsafe fn encrypt(
locations: &[crate::implementation::Location],
mechanism: crate::AZIOT_KEYS_ENCRYPT_MECHANISM,
_parameters: *const std::ffi::c_void,
plaintext: &[u8],
) -> Result<(usize, Vec<u8>), crate::AZIOT_KEYS_RC> {
let Some(key_pair) = load_inner(locations, false)? else {
return Err(crate::implementation::err_invalid_parameter(
"id",
"key not found",
));
};
let (result_len, result) = match key_pair {
KeyPair::FileSystem(_, private_key) => {
let padding = match mechanism {
crate::AZIOT_KEYS_ENCRYPT_MECHANISM_RSA_PKCS1 => openssl::rsa::Padding::PKCS1,
crate::AZIOT_KEYS_ENCRYPT_MECHANISM_RSA_NO_PADDING => openssl::rsa::Padding::NONE,
_ => {
return Err(crate::implementation::err_invalid_parameter(
"mechanism",
"unrecognized value",
))
}
};
let rsa = private_key.rsa().map_err(|_e| {
crate::implementation::err_invalid_parameter("mechanism", "not an RSA key")
})?;
let result_len = rsa.size().try_into().map_err(|err| {
crate::implementation::err_external(format!(
"RSA_size returned invalid value: {err}"
))
})?;
let mut result = vec![0_u8; result_len];
let result_len = rsa.private_encrypt(plaintext, &mut result, padding)?;
(result_len, result)
}
KeyPair::Pkcs11(pkcs11::KeyPair::Ec(_, _)) => {
return Err(crate::implementation::err_invalid_parameter(
"mechanism",
"unrecognized value",
))
}
KeyPair::Pkcs11(pkcs11::KeyPair::Rsa(public_key, private_key)) => {
let mechanism = match mechanism {
crate::AZIOT_KEYS_ENCRYPT_MECHANISM_RSA_PKCS1 => pkcs11::RsaSignMechanism::Pkcs1,
crate::AZIOT_KEYS_ENCRYPT_MECHANISM_RSA_NO_PADDING => {
pkcs11::RsaSignMechanism::X509
}
_ => {
return Err(crate::implementation::err_invalid_parameter(
"mechanism",
"unrecognized value",
))
}
};
let result_len = {
let rsa = public_key.parameters().map_err(|err| {
crate::implementation::err_external(format!(
"could not get key pair parameters: {err}"
))
})?;
let result_len = rsa.size().try_into().map_err(|err| {
crate::implementation::err_external(format!(
"RSA_size returned invalid value: {err}"
))
})?;
result_len
};
let result = {
let mut signature = vec![0_u8; result_len];
let signature_len = private_key
.sign(&mechanism, plaintext, &mut signature)
.map_err(|err| {
crate::implementation::err_external(format!("could not encrypt: {err}"))
})?;
let signature_len = signature_len.try_into().expect("CK_ULONG -> usize");
signature.truncate(signature_len);
signature
};
(result_len, result)
}
};
Ok((result_len, result))
}
enum KeyPair {
FileSystem(
openssl::pkey::PKey<openssl::pkey::Public>,
openssl::pkey::PKey<openssl::pkey::Private>,
),
Pkcs11(pkcs11::KeyPair),
}
impl KeyPair {
fn ec_key(&self) -> Result<openssl::ec::EcKey<openssl::pkey::Public>, crate::AZIOT_KEYS_RC> {
let ec_key = match self {
KeyPair::FileSystem(public_key, _) => public_key.ec_key().ok(),
KeyPair::Pkcs11(pkcs11::KeyPair::Ec(public_key, _)) => {
let ec_key = public_key.parameters().map_err(|err| {
crate::implementation::err_external(format!(
"could not get key pair parameters: {err}"
))
})?;
Some(ec_key)
}
KeyPair::Pkcs11(pkcs11::KeyPair::Rsa(_, _)) => None,
};
let ec_key = ec_key.ok_or_else(|| {
crate::implementation::err_invalid_parameter("type", "not an EC key pair")
})?;
Ok(ec_key)
}
fn rsa(&self) -> Result<openssl::rsa::Rsa<openssl::pkey::Public>, crate::AZIOT_KEYS_RC> {
let rsa = match self {
KeyPair::FileSystem(public_key, _) => public_key.rsa().ok(),
KeyPair::Pkcs11(pkcs11::KeyPair::Ec(_, _)) => None,
KeyPair::Pkcs11(pkcs11::KeyPair::Rsa(public_key, _)) => {
let rsa = public_key.parameters().map_err(|err| {
crate::implementation::err_external(format!(
"could not get key pair public parameters: {err}"
))
})?;
Some(rsa)
}
};
let rsa = rsa.ok_or_else(|| {
crate::implementation::err_invalid_parameter("type", "not an RSA key pair")
})?;
Ok(rsa)
}
}
fn load_inner(
locations: &[crate::implementation::Location],
treat_malformed_as_missing: bool,
) -> Result<Option<KeyPair>, crate::AZIOT_KEYS_RC> {
for location in locations {
match location {
crate::implementation::Location::Filesystem(path) => match std::fs::read(path) {
Ok(private_key_pem) => {
let private_key =
match openssl::pkey::PKey::private_key_from_pem(&private_key_pem) {
Ok(private_key) => private_key,
Err(_) if treat_malformed_as_missing => continue,
Err(err) => return Err(err.into()),
};
// Copy private_key's public parameters into a new public key
let public_key_der = private_key.public_key_to_der()?;
let public_key = openssl::pkey::PKey::public_key_from_der(&public_key_der)?;
return Ok(Some(KeyPair::FileSystem(public_key, private_key)));
}
Err(err) if err.kind() == std::io::ErrorKind::NotFound => (),
Err(err) => return Err(crate::implementation::err_external(err)),
},
crate::implementation::Location::Pkcs11 { lib_path, uri } => {
let pkcs11_context = pkcs11::Context::load(lib_path.clone())
.map_err(crate::implementation::err_external)?;
let pkcs11_slot = pkcs11_context
.find_slot(&uri.slot_identifier)
.map_err(crate::implementation::err_external)?;
let pkcs11_session = pkcs11_context
.open_session(pkcs11_slot, uri.pin.clone())
.map_err(crate::implementation::err_external)?;
match pkcs11_session.get_key_pair(uri.object_label.as_deref()) {
Ok(key_pair) => return Ok(Some(KeyPair::Pkcs11(key_pair))),
Err(pkcs11::GetKeyError::KeyDoesNotExist) => (),
Err(err) => return Err(crate::implementation::err_external(err)),
}
}
}
}
Ok(None)
}
fn create_inner(
locations: &[crate::implementation::Location],
preferred_algorithms: &[PreferredAlgorithm],
) -> Result<(), crate::AZIOT_KEYS_RC> {
let location = locations
.first()
.ok_or_else(|| crate::implementation::err_external("no valid location for key pair"))?;
match location {
crate::implementation::Location::Filesystem(path) => {
let preferred_algorithm =
preferred_algorithms.iter().copied().next().ok_or_else(|| {
crate::implementation::err_invalid_parameter(
"preferred_algorithms",
"none specified",
)
})?;
let private_key = match preferred_algorithm {
PreferredAlgorithm::NistP256 => {
let mut group =
openssl::ec::EcGroup::from_curve_name(openssl::nid::Nid::X9_62_PRIME256V1)?;
group.set_asn1_flag(openssl::ec::Asn1Flag::NAMED_CURVE);
let ec_key = openssl::ec::EcKey::generate(&group)?;
let private_key = openssl::pkey::PKey::from_ec_key(ec_key)?;
private_key
}
PreferredAlgorithm::Rsa2048 => {
let rsa = openssl::rsa::Rsa::generate(2048)?;
let private_key = openssl::pkey::PKey::from_rsa(rsa)?;
private_key
}
PreferredAlgorithm::Rsa4096 => {
let rsa = openssl::rsa::Rsa::generate(4096)?;
let private_key = openssl::pkey::PKey::from_rsa(rsa)?;
private_key
}
};
let private_key_pem = private_key.private_key_to_pem_pkcs8()?;
std::fs::write(path, private_key_pem).map_err(crate::implementation::err_external)?;
Ok(())
}
crate::implementation::Location::Pkcs11 { lib_path, uri } => {
let pkcs11_context = pkcs11::Context::load(lib_path.clone())
.map_err(crate::implementation::err_external)?;
let pkcs11_slot = pkcs11_context
.find_slot(&uri.slot_identifier)
.map_err(crate::implementation::err_external)?;
let pkcs11_session = pkcs11_context
.open_session(pkcs11_slot, uri.pin.clone())
.map_err(crate::implementation::err_external)?;
for preferred_algorithm in preferred_algorithms {
match preferred_algorithm {
PreferredAlgorithm::NistP256 => {
if pkcs11_session
.clone()
.generate_ec_key_pair(
openssl2::EcCurve::NistP256,
uri.object_label.as_deref(),
)
.is_ok()
{
return Ok(());
}
}
PreferredAlgorithm::Rsa2048 => {
let exponent = openssl_sys::RSA_F4;
let exponent = exponent.to_be_bytes();
let exponent = openssl::bn::BigNum::from_slice(&exponent)?;
if pkcs11_session
.clone()
.generate_rsa_key_pair(2048, &exponent, uri.object_label.as_deref())
.is_ok()
{
return Ok(());
}
}
PreferredAlgorithm::Rsa4096 => {
let exponent = openssl_sys::RSA_F4;
let exponent = exponent.to_be_bytes();
let exponent = openssl::bn::BigNum::from_slice(&exponent)?;
if pkcs11_session
.clone()
.generate_rsa_key_pair(4096, &exponent, uri.object_label.as_deref())
.is_ok()
{
return Ok(());
}
}
}
}
Err(crate::implementation::err_invalid_parameter(
"preferred_algorithms",
"no algorithm succeeded",
))
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
enum PreferredAlgorithm {
NistP256,
Rsa2048,
Rsa4096,
}
impl PreferredAlgorithm {
unsafe fn from_str(
s: *const std::os::raw::c_char,
) -> Result<Vec<Self>, Box<dyn std::error::Error>> {
fn add_if_not_exists<T>(v: &mut Vec<T>, element: T)
where
T: std::cmp::PartialEq,
{
if v.iter().any(|existing| existing == &element) {
return;
}
v.push(element);
}
if s.is_null() {
return Ok(vec![
PreferredAlgorithm::NistP256,
PreferredAlgorithm::Rsa2048,
]);
}
let s = std::ffi::CStr::from_ptr(s);
let s = s.to_str()?;
let mut result = vec![];
for component in s.split(':') {
match component {
"*" => {
add_if_not_exists(&mut result, PreferredAlgorithm::NistP256);
add_if_not_exists(&mut result, PreferredAlgorithm::Rsa2048);
}
"ec-p256" => add_if_not_exists(&mut result, PreferredAlgorithm::NistP256),
"rsa-2048" => add_if_not_exists(&mut result, PreferredAlgorithm::Rsa2048),
"rsa-4096" => add_if_not_exists(&mut result, PreferredAlgorithm::Rsa4096),
_ => (),
}
}
Ok(result)
}
}
fn delete_inner(locations: &[crate::implementation::Location]) -> Result<(), crate::AZIOT_KEYS_RC> {
for location in locations {
match location {
crate::implementation::Location::Filesystem(path) => match std::fs::remove_file(path) {
Ok(()) => (),
Err(err) if err.kind() == std::io::ErrorKind::NotFound => (),
Err(err) => return Err(crate::implementation::err_external(err)),
},
crate::implementation::Location::Pkcs11 { lib_path, uri } => {
let pkcs11_context = pkcs11::Context::load(lib_path.clone())
.map_err(crate::implementation::err_external)?;
let pkcs11_slot = pkcs11_context
.find_slot(&uri.slot_identifier)
.map_err(crate::implementation::err_external)?;
let pkcs11_session = pkcs11_context
.open_session(pkcs11_slot, uri.pin.clone())
.map_err(crate::implementation::err_external)?;
let object_label =
uri.object_label.as_deref()
.ok_or_else(|| crate::implementation::err_invalid_parameter(
"id",
"key corresponding to this ID cannot be deleted because it is a PKCS#11 key without an object label",
))?;
match pkcs11_session.delete_key_pair(object_label) {
Ok(()) => (),
Err(err) => return Err(crate::implementation::err_external(err)),
}
}
}
}
Ok(())
}
fn move_inner(
from: &[crate::implementation::Location],
to: &[crate::implementation::Location],
) -> Result<(), crate::AZIOT_KEYS_RC> {
let from = from.first().ok_or_else(|| {
crate::implementation::err_external("no valid location for source key pair")
})?;
let to = to.first().ok_or_else(|| {
crate::implementation::err_external("no valid location for destination key pair")
})?;
match (from, to) {
(
crate::implementation::Location::Filesystem(from),
crate::implementation::Location::Filesystem(to),
) => {
// Rename key in filesystem.
std::fs::rename(from, to).map_err(crate::implementation::err_external)
}
(
crate::implementation::Location::Filesystem(_),
crate::implementation::Location::Pkcs11 { .. },
) => {
// Importing a key using this function is not supported.
Err(crate::implementation::err_invalid_parameter(
"to",
"cannot move filesystem key to pkcs11",
))
}
(
crate::implementation::Location::Pkcs11 {
lib_path: lib_path_from,
uri: from,
},
crate::implementation::Location::Pkcs11 {
lib_path: lib_path_to,
uri: to,
},
) => {
let from_label = from.object_label.as_deref().ok_or_else(|| {
crate::implementation::err_invalid_parameter(
"from",
"source key missing object label",
)
})?;
let to_label = to.object_label.as_deref().ok_or_else(|| {
crate::implementation::err_invalid_parameter(
"to",
"destination key missing object label",
)
})?;
// Delete any existing key pair with the 'to' label.
let pkcs11_context = pkcs11::Context::load(lib_path_to.clone())
.map_err(crate::implementation::err_external)?;
let pkcs11_slot = pkcs11_context
.find_slot(&to.slot_identifier)
.map_err(crate::implementation::err_external)?;
let pkcs11_session = pkcs11_context
.open_session(pkcs11_slot, to.pin.clone())
.map_err(crate::implementation::err_external)?;
pkcs11_session
.delete_key_pair(to_label)
.map_err(crate::implementation::err_external)?;
// Rename key by changing label.
let pkcs11_context = pkcs11::Context::load(lib_path_from.clone())
.map_err(crate::implementation::err_external)?;
let pkcs11_slot = pkcs11_context
.find_slot(&from.slot_identifier)
.map_err(crate::implementation::err_external)?;
let pkcs11_session = pkcs11_context
.open_session(pkcs11_slot, from.pin.clone())
.map_err(crate::implementation::err_external)?;
pkcs11_session
.rename_key_pair(from_label, to_label)
.map_err(crate::implementation::err_external)
}
(
crate::implementation::Location::Pkcs11 { .. },
crate::implementation::Location::Filesystem(_),
) => {
// Cannot export keys to filesystem.
Err(crate::implementation::err_invalid_parameter(
"to",
"cannot move pkcs11 key to filesystem",
))
}
}
}