feat: update pkcs11 piv

This commit is contained in:
2024-07-06 19:44:10 +08:00
parent a77e6ff44e
commit 1b174db255
6 changed files with 219 additions and 480 deletions

View File

@@ -12,14 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::{collections::HashMap, sync::Arc};
use std::sync::Arc;
use core_foundation::{
base::{TCFType, ToVoid},
string::CFString,
};
use security_framework::{item::KeyClass, key::SecKey};
use security_framework_sys::item::kSecAttrLabel;
use tracing::instrument;
use native_pkcs11_traits::Backend;
@@ -30,17 +24,6 @@ use native_pkcs11_traits::PrivateKey as P11PrivateKey;
use native_pkcs11_traits::PublicKey as P11PublicKey;
use native_pkcs11_traits::Result as P11Result;
use crate::{
certificate::{find_all_certificates, YubikeyPivCertificate},
key::{
find_all_keys,
find_key,
find_key2,
YubikeyPivPrivateKey,
YubikeyPivPublicKey,
},
};
#[derive(Debug, Default)]
pub struct YubikeyPivBackend;
@@ -52,20 +35,21 @@ impl YubikeyPivBackend {
impl Backend for YubikeyPivBackend {
fn name(&self) -> String {
"Keychain".into()
"Yubikey PIV".into()
}
#[instrument]
fn find_all_certificates(
&self,
) -> P11Result<Vec<Box<dyn P11Certificate>>> {
let certs = find_all_certificates()?
.into_iter()
.map(YubikeyPivCertificate::new)
.filter_map(Result::ok)
.map(|cert| Box::new(cert) as _)
.collect();
Ok(certs)
Ok(vec![])
// let certs = find_all_certificates()?
// .into_iter()
// .map(YubikeyPivCertificate::new)
// .filter_map(Result::ok)
// .map(|cert| Box::new(cert) as _)
// .collect();
// Ok(certs)
}
#[instrument]
@@ -73,41 +57,42 @@ impl Backend for YubikeyPivBackend {
&self,
query: P11KeySearchOptions,
) -> P11Result<Option<Arc<dyn P11PrivateKey>>> {
let mut pubkeys_by_pubkey_hash: HashMap<Vec<u8>, SecKey> =
HashMap::from_iter(find_all_certificates()?.into_iter().filter_map(|c| {
c.certificate()
.ok()
.and_then(|cert| cert.public_key().ok())
.and_then(|pk| pk.application_label().map(|pubkey_hash| (pubkey_hash, pk)))
}));
let mut find_pubkey_for_seckey = |sec_key: &SecKey| -> Option<YubikeyPivPublicKey> {
sec_key
.application_label()
.and_then(|pubkey_hash| pubkeys_by_pubkey_hash.remove(&pubkey_hash))
// TODO(kcking): populate label if searching by label
.and_then(|sec_key| YubikeyPivPublicKey::new(sec_key, "").ok())
};
let opt_key = match query {
P11KeySearchOptions::Label(label) => {
find_key(KeyClass::private(), &label)
.ok()
.map(|sec_key| {
let cert = find_pubkey_for_seckey(&sec_key);
YubikeyPivPrivateKey::new(sec_key, label, cert)
})
.transpose()?
}
P11KeySearchOptions::PublicKeyHash(public_key_hash) => {
find_key2(KeyClass::private(), &public_key_hash)?
.map(|sec_key| {
let cert = find_pubkey_for_seckey(&sec_key);
YubikeyPivPrivateKey::new(sec_key, "", cert)
})
.transpose()?
}
};
Ok(opt_key.map(|sec_key| Arc::new(sec_key) as _))
Ok(None)
// let mut pubkeys_by_pubkey_hash: HashMap<Vec<u8>, SecKey> =
// HashMap::from_iter(find_all_certificates()?.into_iter().filter_map(|c| {
// c.certificate()
// .ok()
// .and_then(|cert| cert.public_key().ok())
// .and_then(|pk| pk.application_label().map(|pubkey_hash| (pubkey_hash, pk)))
// }));
//
// let mut find_pubkey_for_seckey = |sec_key: &SecKey| -> Option<YubikeyPivPublicKey> {
// sec_key
// .application_label()
// .and_then(|pubkey_hash| pubkeys_by_pubkey_hash.remove(&pubkey_hash))
// // TODO(kcking): populate label if searching by label
// .and_then(|sec_key| YubikeyPivPublicKey::new(sec_key, "").ok())
// };
// let opt_key = match query {
// P11KeySearchOptions::Label(label) => {
// find_key(KeyClass::private(), &label)
// .ok()
// .map(|sec_key| {
// let cert = find_pubkey_for_seckey(&sec_key);
// YubikeyPivPrivateKey::new(sec_key, label, cert)
// })
// .transpose()?
// }
// P11KeySearchOptions::PublicKeyHash(public_key_hash) => {
// find_key2(KeyClass::private(), &public_key_hash)?
// .map(|sec_key| {
// let cert = find_pubkey_for_seckey(&sec_key);
// YubikeyPivPrivateKey::new(sec_key, "", cert)
// })
// .transpose()?
// }
// };
// Ok(opt_key.map(|sec_key| Arc::new(sec_key) as _))
}
#[instrument]
@@ -115,20 +100,68 @@ impl Backend for YubikeyPivBackend {
&self,
query: P11KeySearchOptions,
) -> P11Result<Option<Box<dyn P11PublicKey>>> {
let opt_key = match query {
P11KeySearchOptions::Label(label) => {
find_key(KeyClass::public(), &label)
.ok()
.map(|sec_key| YubikeyPivPublicKey::new(sec_key, label))
.transpose()?
}
P11KeySearchOptions::PublicKeyHash(public_key_hash) => {
find_key2(KeyClass::public(), &public_key_hash)?
.map(|sec_key| YubikeyPivPublicKey::new(sec_key, ""))
.transpose()?
}
};
Ok(opt_key.map(|sec_key| Box::new(sec_key) as _))
Ok(None)
// let opt_key = match query {
// P11KeySearchOptions::Label(label) => {
// find_key(KeyClass::public(), &label)
// .ok()
// .map(|sec_key| YubikeyPivPublicKey::new(sec_key, label))
// .transpose()?
// }
// P11KeySearchOptions::PublicKeyHash(public_key_hash) => {
// find_key2(KeyClass::public(), &public_key_hash)?
// .map(|sec_key| YubikeyPivPublicKey::new(sec_key, ""))
// .transpose()?
// }
// };
// Ok(opt_key.map(|sec_key| Box::new(sec_key) as _))
}
fn find_all_private_keys(
&self,
) -> P11Result<Vec<Arc<dyn P11PrivateKey>>> {
Ok(vec![])
// let sec_keys = find_all_keys(KeyClass::private())?;
// let keys = sec_keys
// .into_iter()
// .filter_map(|sec_key| {
// let label: Option<String> = sec_key
// .attributes()
// .find(unsafe { kSecAttrLabel }.to_void())
// .map(|label| {
// unsafe { CFString::wrap_under_get_rule(label.cast()) }.to_string()
// });
// let label: String = label.unwrap_or_default();
//
// YubikeyPivPrivateKey::new(sec_key, label, None).ok()
// })
// .map(|k| Arc::new(k) as _);
//
// Ok(keys.collect())
}
fn find_all_public_keys(
&self,
) -> P11Result<Vec<Arc<dyn P11PublicKey>>> {
Ok(vec![])
// let sec_keys = find_all_keys(KeyClass::public())?;
//
// let keys = sec_keys
// .into_iter()
// .filter_map(|sec_key| {
// let label: Option<String> = sec_key
// .attributes()
// .find(unsafe { kSecAttrLabel }.to_void())
// .map(|label| {
// unsafe { CFString::wrap_under_get_rule(label.cast()) }.to_string()
// });
// let label: String = label.unwrap_or_default();
//
// YubikeyPivPublicKey::new(sec_key, label).ok()
// })
// .map(|k| Arc::new(k) as _);
//
// Ok(keys.collect())
}
#[instrument]
@@ -139,49 +172,4 @@ impl Backend for YubikeyPivBackend {
) -> P11Result<Arc<dyn P11PrivateKey>> {
Err("Generate key not supported, please use ykman, URL: https://hatter.in/ykman")?
}
fn find_all_private_keys(
&self,
) -> P11Result<Vec<Arc<dyn P11PrivateKey>>> {
let sec_keys = find_all_keys(KeyClass::private())?;
let keys = sec_keys
.into_iter()
.filter_map(|sec_key| {
let label: Option<String> = sec_key
.attributes()
.find(unsafe { kSecAttrLabel }.to_void())
.map(|label| {
unsafe { CFString::wrap_under_get_rule(label.cast()) }.to_string()
});
let label: String = label.unwrap_or_default();
YubikeyPivPrivateKey::new(sec_key, label, None).ok()
})
.map(|k| Arc::new(k) as _);
Ok(keys.collect())
}
fn find_all_public_keys(
&self,
) -> P11Result<Vec<Arc<dyn P11PublicKey>>> {
let sec_keys = find_all_keys(KeyClass::public())?;
let keys = sec_keys
.into_iter()
.filter_map(|sec_key| {
let label: Option<String> = sec_key
.attributes()
.find(unsafe { kSecAttrLabel }.to_void())
.map(|label| {
unsafe { CFString::wrap_under_get_rule(label.cast()) }.to_string()
});
let label: String = label.unwrap_or_default();
YubikeyPivPublicKey::new(sec_key, label).ok()
})
.map(|k| Arc::new(k) as _);
Ok(keys.collect())
}
}