feat: update pkcs11 piv
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user