feat: update pkcs11 piv

This commit is contained in:
2024-07-06 21:42:41 +08:00
parent 1b174db255
commit a7bfda9cbf
5 changed files with 92 additions and 422 deletions

View File

@@ -14,76 +14,18 @@
use std::fmt::Debug;
use core_foundation::base::ToVoid;
use security_framework::{
item::{ItemClass, KeyClass, Limit, Reference},
key::SecKey,
};
// TODO(bweeks,kcking): remove dependency on security-framework-sys crate.
use security_framework_sys::item::{
kSecAttrKeyType,
kSecAttrKeyTypeEC,
kSecAttrKeyTypeRSA,
kSecAttrTokenID,
};
use security_framework::key::SecKey;
use tracing::instrument;
use native_pkcs11_traits::{KeyAlgorithm, PrivateKey, PublicKey, SignatureAlgorithm};
use native_pkcs11_traits::DigestType as P11DigestType;
use native_pkcs11_traits::{Backend, KeyAlgorithm, PrivateKey, PublicKey, SignatureAlgorithm};
use native_pkcs11_traits::Result as P11Result;
use crate::Result;
#[derive(Debug)]
pub enum Algorithm {
RSA,
ECC,
}
fn sigalg_to_seckeyalg(
signature_algorithm: &SignatureAlgorithm,
) -> Result<security_framework_sys::key::Algorithm> {
use security_framework_sys::key::Algorithm::*;
let alg = match signature_algorithm {
SignatureAlgorithm::Ecdsa => ECDSASignatureRFC4754,
SignatureAlgorithm::RsaRaw => RSASignatureRaw,
SignatureAlgorithm::RsaPkcs1v15Raw => RSASignatureDigestPKCS1v15Raw,
SignatureAlgorithm::RsaPkcs1v15Sha1 => {
RSASignatureMessagePKCS1v15SHA1
}
SignatureAlgorithm::RsaPkcs1v15Sha384 => {
RSASignatureMessagePKCS1v15SHA384
}
SignatureAlgorithm::RsaPkcs1v15Sha256 => {
RSASignatureMessagePKCS1v15SHA256
}
SignatureAlgorithm::RsaPkcs1v15Sha512 => {
RSASignatureMessagePKCS1v15SHA512
}
SignatureAlgorithm::RsaPss {
digest,
mask_generation_function,
salt_length,
} => {
// SecurityFramework only supports digest == mgf, salt_length == len(digest).
if digest != mask_generation_function || digest.digest_len() != *salt_length as usize {
return Err(crate::ErrorKind::UnsupportedSignatureAlgorithm(
signature_algorithm.clone(),
)
.into());
}
match mask_generation_function {
P11DigestType::Sha1 => RSASignatureDigestPSSSHA1,
P11DigestType::Sha224 => RSASignatureDigestPSSSHA224,
P11DigestType::Sha256 => RSASignatureDigestPSSSHA256,
P11DigestType::Sha384 => RSASignatureDigestPSSSHA384,
P11DigestType::Sha512 => RSASignatureDigestPSSSHA512,
}
}
};
Ok(alg)
}
#[derive(Debug)]
pub struct YubikeyPivPrivateKey {
sec_key: SecKey,
@@ -94,22 +36,22 @@ pub struct YubikeyPivPrivateKey {
}
impl YubikeyPivPrivateKey {
#[instrument]
pub fn new(
sec_key: SecKey,
label: impl Into<String> + Debug,
pub_key: Option<YubikeyPivPublicKey>,
) -> Result<Self> {
let label = label.into();
let public_key_hash = sec_key.application_label().ok_or("no application_label")?;
Ok(Self {
algorithm: sec_key_algorithm(&sec_key)?,
sec_key,
label,
public_key_hash,
pub_key,
})
}
// #[instrument]
// pub fn new(
// sec_key: SecKey,
// label: impl Into<String> + Debug,
// pub_key: Option<YubikeyPivPublicKey>,
// ) -> Result<Self> {
// let label = label.into();
// let public_key_hash = sec_key.application_label().ok_or("no application_label")?;
// Ok(Self {
// algorithm: sec_key_algorithm(&sec_key)?,
// sec_key,
// label,
// public_key_hash,
// pub_key,
// })
// }
}
impl PrivateKey for YubikeyPivPrivateKey {
@@ -129,62 +71,38 @@ impl PrivateKey for YubikeyPivPrivateKey {
algorithm: &SignatureAlgorithm,
data: &[u8],
) -> P11Result<Vec<u8>> {
let algorithm = sigalg_to_seckeyalg(algorithm)?;
Ok(self.sec_key.create_signature(algorithm, data.as_ref())?)
match algorithm {
SignatureAlgorithm::Ecdsa => {}
SignatureAlgorithm::RsaRaw => {}
SignatureAlgorithm::RsaPkcs1v15Raw => {}
SignatureAlgorithm::RsaPkcs1v15Sha1 => {}
SignatureAlgorithm::RsaPkcs1v15Sha384 => {}
SignatureAlgorithm::RsaPkcs1v15Sha256 => {}
SignatureAlgorithm::RsaPkcs1v15Sha512 => {}
SignatureAlgorithm::RsaPss { .. } => {}
}
// TODO sign data or hash??
Ok(vec![])
}
#[instrument]
fn delete(&self) {
let _ = self.sec_key.delete();
// yubikey-piv-pkcs11 just cannot delete private key
}
#[instrument]
fn algorithm(&self) -> KeyAlgorithm {
self.algorithm
}
fn find_public_key(
&self,
_backend: &dyn native_pkcs11_traits::Backend,
_backend: &dyn Backend,
) -> P11Result<Option<Box<dyn PublicKey>>> {
let sec_copy = self
.sec_key
.public_key()
.map(|sec_key| YubikeyPivPublicKey::new(sec_key, self.label()))
.transpose()
.ok()
.flatten()
.map(|key| Box::new(key) as _);
if sec_copy.is_some() {
return Ok(sec_copy);
}
Ok(self.pub_key.clone().map(|key| Box::new(key) as _))
Ok(None)
}
}
fn sec_key_algorithm(sec_key: &SecKey) -> Result<KeyAlgorithm> {
let attributes = sec_key.attributes();
if attributes
.find(unsafe { kSecAttrTokenID }.to_void())
.is_some()
{
// The only possible kSecAttrtokenID is kSecAttrTokenIDSecureEnclave.
//
// SecureEnclave keys do not have kSecAttrKeyType populated, but we can
// assume they are Ecc.
return Ok(KeyAlgorithm::Ecc);
}
let key_ty = sec_key
.attributes()
.find(unsafe { kSecAttrKeyType }.to_void())
.and_then(|key_type| match *key_type as *const _ {
ty if ty == unsafe { kSecAttrKeyTypeRSA } => Some(KeyAlgorithm::Rsa),
ty if ty == unsafe { kSecAttrKeyTypeEC } => Some(KeyAlgorithm::Ecc),
_ => None,
})
.ok_or("no key type")?;
Ok(key_ty)
}
#[derive(Debug, Clone)]
pub struct YubikeyPivPublicKey {
pub sec_key: SecKey,
@@ -195,20 +113,20 @@ pub struct YubikeyPivPublicKey {
}
impl YubikeyPivPublicKey {
#[instrument]
pub fn new(sec_key: SecKey, label: impl Into<String> + Debug) -> Result<Self> {
let der = sec_key
.external_representation()
.ok_or("no external representation")?;
let key_ty = sec_key_algorithm(&sec_key)?;
Ok(Self {
public_key_hash: sec_key.application_label().ok_or("no application_label")?,
sec_key,
label: label.into(),
der: der.to_vec(),
algorithm: key_ty,
})
}
// #[instrument]
// pub fn new(sec_key: SecKey, label: impl Into<String> + Debug) -> Result<Self> {
// let der = sec_key
// .external_representation()
// .ok_or("no external representation")?;
// let key_ty = sec_key_algorithm(&sec_key)?;
// Ok(Self {
// public_key_hash: sec_key.application_label().ok_or("no application_label")?,
// sec_key,
// label: label.into(),
// der: der.to_vec(),
// algorithm: key_ty,
// })
// }
}
impl PublicKey for YubikeyPivPublicKey {
@@ -230,15 +148,15 @@ impl PublicKey for YubikeyPivPublicKey {
#[instrument]
fn verify(
&self,
algorithm: &native_pkcs11_traits::SignatureAlgorithm,
algorithm: &SignatureAlgorithm,
data: &[u8],
signature: &[u8],
) -> P11Result<()> {
let algorithm = sigalg_to_seckeyalg(algorithm)?;
let result = self.sec_key.verify_signature(algorithm, data, signature)?;
if !result {
return Err("verify failed")?;
}
// let algorithm = sigalg_to_seckeyalg(algorithm)?;
// let result = self.sec_key.verify_signature(algorithm, data, signature)?;
// if !result {
// return Err("verify failed")?;
// }
Ok(())
}
@@ -250,77 +168,3 @@ impl PublicKey for YubikeyPivPublicKey {
self.algorithm
}
}
pub fn find_key(class: KeyClass, label: &str) -> Result<SecKey> {
Err("")?
// let results = crate::keychain::item_search_options()?
// .load_refs(true)
// .label(label)
// .class(ItemClass::key())
// .key_class(class)
// .limit(1)
// .search();
//
// let loaded_key = match results?.into_iter().next().ok_or("key not found")? {
// security_framework::item::SearchResult::Ref(Reference::Key(key)) => key,
// _ => return Err("no key ref")?,
// };
//
// Ok(loaded_key)
}
#[instrument]
pub fn find_key2(class: KeyClass, label: &[u8]) -> Result<Option<SecKey>> {
Ok(None)
// let results = crate::keychain::item_search_options()?
// .load_refs(true)
// .class(ItemClass::key())
// .key_class(class)
// .application_label(label)
// .limit(1)
// .search();
//
// let results = match results {
// Err(e) if e.code() == -25300 => return Ok(None),
// Err(e) => return Err(e)?,
// Ok(results) => results,
// };
//
// let loaded_key = results
// .into_iter()
// .next()
// .map(|key| match key {
// security_framework::item::SearchResult::Ref(Reference::Key(key)) => Ok::<_, &str>(key),
// _ => Err("no key ref")?,
// })
// .transpose()?;
//
// Ok(loaded_key)
}
#[instrument]
pub fn find_all_keys(key_class: KeyClass) -> Result<Vec<SecKey>> {
Ok(vec![])
// let results = crate::keychain::item_search_options()?
// .load_refs(true)
// .class(ItemClass::key())
// .key_class(key_class)
// .limit(Limit::All)
// .search();
//
// let results = match results {
// Err(e) if e.code() == -25300 => return Ok(vec![]),
// Err(e) => return Err(e)?,
// Ok(results) => results,
// };
//
// let keys = results
// .into_iter()
// .filter_map(|res| match res {
// security_framework::item::SearchResult::Ref(Reference::Key(key)) => Some(key),
// _ => None,
// })
// .collect();
//
// Ok(keys)
}