diff --git a/Cargo.lock b/Cargo.lock index 7b66c24..f16f674 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -563,9 +563,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", diff --git a/native-pkcs11-piv/src/piv/backend.rs b/native-pkcs11-piv/src/piv/backend.rs index 5fe7015..0d8bf25 100644 --- a/native-pkcs11-piv/src/piv/backend.rs +++ b/native-pkcs11-piv/src/piv/backend.rs @@ -16,7 +16,7 @@ use std::sync::Arc; use tracing::instrument; -use native_pkcs11_traits::Backend; +use native_pkcs11_traits::{Backend, KeySearchOptions}; use native_pkcs11_traits::Certificate as P11Certificate; use native_pkcs11_traits::KeyAlgorithm as P11KeyAlgorithm; use native_pkcs11_traits::KeySearchOptions as P11KeySearchOptions; @@ -43,13 +43,6 @@ impl Backend for YubikeyPivBackend { &self, ) -> P11Result>> { 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] @@ -57,42 +50,11 @@ impl Backend for YubikeyPivBackend { &self, query: P11KeySearchOptions, ) -> P11Result>> { + match query { + KeySearchOptions::Label(label) => {} + KeySearchOptions::PublicKeyHash(public_key_hash) => {} + } Ok(None) - // let mut pubkeys_by_pubkey_hash: HashMap, 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 { - // 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] @@ -100,68 +62,23 @@ impl Backend for YubikeyPivBackend { &self, query: P11KeySearchOptions, ) -> P11Result>> { + match query { + KeySearchOptions::Label(label) => {} + KeySearchOptions::PublicKeyHash(public_key_hash) => {} + } 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>> { Ok(vec![]) - // let sec_keys = find_all_keys(KeyClass::private())?; - // let keys = sec_keys - // .into_iter() - // .filter_map(|sec_key| { - // let label: Option = 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>> { Ok(vec![]) - // let sec_keys = find_all_keys(KeyClass::public())?; - // - // let keys = sec_keys - // .into_iter() - // .filter_map(|sec_key| { - // let label: Option = 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] diff --git a/native-pkcs11-piv/src/piv/certificate.rs b/native-pkcs11-piv/src/piv/certificate.rs index 32a0c8d..7610a2d 100644 --- a/native-pkcs11-piv/src/piv/certificate.rs +++ b/native-pkcs11-piv/src/piv/certificate.rs @@ -12,78 +12,35 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{ - str::FromStr, - time::{Duration, SystemTime}, -}; - -use rsa::{pkcs1::DecodeRsaPublicKey, pkcs8::AssociatedOid}; -use security_framework::{ - certificate::SecCertificate, - identity::SecIdentity, - item::{add_item, AddRef, ItemAddOptions, ItemClass, Reference}, - key::SecKey, - os::macos::identity::SecIdentityExt, -}; -use security_framework_sys::base::errSecItemNotFound; -use x509_cert::{ - Certificate, - der::{ - asn1::{GeneralizedTime, Ia5String, OctetString}, - Decode, - Encode, - oid::ObjectIdentifier, - }, - ext::{ - Extension, - pkix::{ - AuthorityKeyIdentifier, - BasicConstraints, - ExtendedKeyUsage, - KeyUsage, - KeyUsages, - name::GeneralName, - SubjectAltName, - SubjectKeyIdentifier, - }, - }, - name::{Name, RdnSequence}, - serial_number::SerialNumber, - spki::{der::asn1::BitString, EncodePublicKey, SubjectPublicKeyInfo}, - TbsCertificate, - time::Validity, -}; +use std::fmt::Debug; use native_pkcs11_traits::Certificate as P11Certificate; -use native_pkcs11_traits::random_label; +use native_pkcs11_traits::PublicKey as P11PublicKey; -use crate::{ - key::{Algorithm, YubikeyPivPublicKey}, - Result, -}; +use crate::key::YubikeyPivPublicKey; pub struct YubikeyPivCertificate { pub label: String, - pub identity: SecIdentity, + pub identity: String, pub public_key: YubikeyPivPublicKey, certificate_der: Vec, } impl YubikeyPivCertificate { - pub fn new(identity: impl Into) -> Result { - let identity: SecIdentity = identity.into(); - let label = identity.certificate().unwrap().subject_summary(); - let pk = identity.certificate()?.public_key()?; - Ok(Self { - certificate_der: identity.certificate()?.to_der(), - label: label.clone(), - identity, - public_key: YubikeyPivPublicKey::new(pk, label)?, - }) - } + // pub fn new(identity: impl Into) -> Result { + // let identity: SecIdentity = identity.into(); + // let label = identity.certificate().unwrap().subject_summary(); + // let pk = identity.certificate()?.public_key()?; + // Ok(Self { + // certificate_der: identity.certificate()?.to_der(), + // label: label.clone(), + // identity, + // public_key: YubikeyPivPublicKey::new(pk, label)?, + // }) + // } } -impl std::fmt::Debug for YubikeyPivCertificate { +impl Debug for YubikeyPivCertificate { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("KeychainCertificate") .field("label", &self.label) @@ -97,57 +54,15 @@ impl P11Certificate for YubikeyPivCertificate { self.label.to_string() } - fn public_key(&self) -> &dyn native_pkcs11_traits::PublicKey { - &self.public_key - } - fn to_der(&self) -> Vec { self.certificate_der.clone() } + fn public_key(&self) -> &dyn P11PublicKey { + &self.public_key + } + fn delete(self: Box) { - let _ = self.identity.delete(); + // yubikey-piv-pkcs11 just cannot delete certificate } } - -pub fn import_certificate(der: &[u8]) -> Result { - Err("")? - // let cert = SecCertificate::from_der(der)?; - // - // let add_params = ItemAddOptions::new(security_framework::item::ItemAddValue::Ref( - // AddRef::Certificate(cert.clone()), - // )) - // .set_location(keychain::location()?) - // .set_label(cert.subject_summary()) - // .to_dictionary(); - // add_item(add_params)?; - // - // Ok(cert) -} - -pub fn find_certificate(pub_key_hash: &[u8]) -> Result> { - Ok(None) - // let results = crate::piv::keychain::item_search_options()? - // .load_refs(true) - // .class(ItemClass::certificate()) - // .pub_key_hash(pub_key_hash) - // .search()?; - // - // if results.is_empty() { - // return Ok(None); - // } - // - // let cert = match results.into_iter().next().ok_or("certificate not found")? { - // security_framework::item::SearchResult::Ref(Reference::Certificate(certificate)) => { - // certificate - // } - // _ => return Err("no key ref")?, - // }; - // - // Ok(Some(SecIdentity::with_certificate(&[], &cert)?)) -} - -pub fn random_serial_number() -> [u8; 16] { - use rand::Rng; - rand::thread_rng().gen::().to_be_bytes() -} diff --git a/native-pkcs11-piv/src/piv/key.rs b/native-pkcs11-piv/src/piv/key.rs index fd8659a..26671c9 100644 --- a/native-pkcs11-piv/src/piv/key.rs +++ b/native-pkcs11-piv/src/piv/key.rs @@ -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 { - 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 + Debug, - pub_key: Option, - ) -> Result { - 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 + Debug, + // pub_key: Option, + // ) -> Result { + // 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> { - 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>> { - 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 { - 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 + Debug) -> Result { - 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 + Debug) -> Result { + // 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 { - 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> { - 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> { - 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) -} diff --git a/native-pkcs11-piv/src/piv/mod.rs b/native-pkcs11-piv/src/piv/mod.rs index a251057..821769e 100644 --- a/native-pkcs11-piv/src/piv/mod.rs +++ b/native-pkcs11-piv/src/piv/mod.rs @@ -12,14 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::fmt::Debug; +use std::fmt::{Debug, Formatter}; -pub use backend::YubikeyPivBackend; -use core_foundation::error::CFError; -use native_pkcs11_traits::SignatureAlgorithm; use thiserror::Error; use tracing_error::SpanTrace; +pub use backend::YubikeyPivBackend; +use native_pkcs11_traits::SignatureAlgorithm; + mod backend; pub mod certificate; pub mod key; @@ -32,7 +32,7 @@ pub struct Error { } impl Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { writeln!(f, "{:?}", self.error)?; self.context.fmt(f) } @@ -50,7 +50,7 @@ impl> From for Error { } impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { writeln!(f, "{}", self.error)?; std::fmt::Display::fmt(&self.context, f) } @@ -80,12 +80,6 @@ pub enum ErrorKind { UnsupportedSignatureAlgorithm(SignatureAlgorithm), } -impl From for ErrorKind { - fn from(e: CFError) -> Self { - ErrorKind::SecurityFramework(security_framework::base::Error::from_code(e.code() as i32)) - } -} - impl From<&str> for ErrorKind { fn from(s: &str) -> Self { ErrorKind::Generic(s.to_string())