feat: update pkcs11 piv
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -563,9 +563,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7"
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use tracing::instrument;
|
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::Certificate as P11Certificate;
|
||||||
use native_pkcs11_traits::KeyAlgorithm as P11KeyAlgorithm;
|
use native_pkcs11_traits::KeyAlgorithm as P11KeyAlgorithm;
|
||||||
use native_pkcs11_traits::KeySearchOptions as P11KeySearchOptions;
|
use native_pkcs11_traits::KeySearchOptions as P11KeySearchOptions;
|
||||||
@@ -43,13 +43,6 @@ impl Backend for YubikeyPivBackend {
|
|||||||
&self,
|
&self,
|
||||||
) -> P11Result<Vec<Box<dyn P11Certificate>>> {
|
) -> P11Result<Vec<Box<dyn P11Certificate>>> {
|
||||||
Ok(vec![])
|
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]
|
#[instrument]
|
||||||
@@ -57,42 +50,11 @@ impl Backend for YubikeyPivBackend {
|
|||||||
&self,
|
&self,
|
||||||
query: P11KeySearchOptions,
|
query: P11KeySearchOptions,
|
||||||
) -> P11Result<Option<Arc<dyn P11PrivateKey>>> {
|
) -> P11Result<Option<Arc<dyn P11PrivateKey>>> {
|
||||||
|
match query {
|
||||||
|
KeySearchOptions::Label(label) => {}
|
||||||
|
KeySearchOptions::PublicKeyHash(public_key_hash) => {}
|
||||||
|
}
|
||||||
Ok(None)
|
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]
|
#[instrument]
|
||||||
@@ -100,68 +62,23 @@ impl Backend for YubikeyPivBackend {
|
|||||||
&self,
|
&self,
|
||||||
query: P11KeySearchOptions,
|
query: P11KeySearchOptions,
|
||||||
) -> P11Result<Option<Box<dyn P11PublicKey>>> {
|
) -> P11Result<Option<Box<dyn P11PublicKey>>> {
|
||||||
|
match query {
|
||||||
|
KeySearchOptions::Label(label) => {}
|
||||||
|
KeySearchOptions::PublicKeyHash(public_key_hash) => {}
|
||||||
|
}
|
||||||
Ok(None)
|
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(
|
fn find_all_private_keys(
|
||||||
&self,
|
&self,
|
||||||
) -> P11Result<Vec<Arc<dyn P11PrivateKey>>> {
|
) -> P11Result<Vec<Arc<dyn P11PrivateKey>>> {
|
||||||
Ok(vec![])
|
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(
|
fn find_all_public_keys(
|
||||||
&self,
|
&self,
|
||||||
) -> P11Result<Vec<Arc<dyn P11PublicKey>>> {
|
) -> P11Result<Vec<Arc<dyn P11PublicKey>>> {
|
||||||
Ok(vec![])
|
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]
|
#[instrument]
|
||||||
|
|||||||
@@ -12,78 +12,35 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::{
|
use std::fmt::Debug;
|
||||||
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 native_pkcs11_traits::Certificate as P11Certificate;
|
use native_pkcs11_traits::Certificate as P11Certificate;
|
||||||
use native_pkcs11_traits::random_label;
|
use native_pkcs11_traits::PublicKey as P11PublicKey;
|
||||||
|
|
||||||
use crate::{
|
use crate::key::YubikeyPivPublicKey;
|
||||||
key::{Algorithm, YubikeyPivPublicKey},
|
|
||||||
Result,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct YubikeyPivCertificate {
|
pub struct YubikeyPivCertificate {
|
||||||
pub label: String,
|
pub label: String,
|
||||||
pub identity: SecIdentity,
|
pub identity: String,
|
||||||
pub public_key: YubikeyPivPublicKey,
|
pub public_key: YubikeyPivPublicKey,
|
||||||
certificate_der: Vec<u8>,
|
certificate_der: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl YubikeyPivCertificate {
|
impl YubikeyPivCertificate {
|
||||||
pub fn new(identity: impl Into<SecIdentity>) -> Result<Self> {
|
// pub fn new(identity: impl Into<SecIdentity>) -> Result<Self> {
|
||||||
let identity: SecIdentity = identity.into();
|
// let identity: SecIdentity = identity.into();
|
||||||
let label = identity.certificate().unwrap().subject_summary();
|
// let label = identity.certificate().unwrap().subject_summary();
|
||||||
let pk = identity.certificate()?.public_key()?;
|
// let pk = identity.certificate()?.public_key()?;
|
||||||
Ok(Self {
|
// Ok(Self {
|
||||||
certificate_der: identity.certificate()?.to_der(),
|
// certificate_der: identity.certificate()?.to_der(),
|
||||||
label: label.clone(),
|
// label: label.clone(),
|
||||||
identity,
|
// identity,
|
||||||
public_key: YubikeyPivPublicKey::new(pk, label)?,
|
// 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 {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("KeychainCertificate")
|
f.debug_struct("KeychainCertificate")
|
||||||
.field("label", &self.label)
|
.field("label", &self.label)
|
||||||
@@ -97,57 +54,15 @@ impl P11Certificate for YubikeyPivCertificate {
|
|||||||
self.label.to_string()
|
self.label.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn public_key(&self) -> &dyn native_pkcs11_traits::PublicKey {
|
|
||||||
&self.public_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_der(&self) -> Vec<u8> {
|
fn to_der(&self) -> Vec<u8> {
|
||||||
self.certificate_der.clone()
|
self.certificate_der.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn public_key(&self) -> &dyn P11PublicKey {
|
||||||
|
&self.public_key
|
||||||
|
}
|
||||||
|
|
||||||
fn delete(self: Box<Self>) {
|
fn delete(self: Box<Self>) {
|
||||||
let _ = self.identity.delete();
|
// yubikey-piv-pkcs11 just cannot delete certificate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn import_certificate(der: &[u8]) -> Result<SecCertificate> {
|
|
||||||
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<Option<SecIdentity>> {
|
|
||||||
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::<u128>().to_be_bytes()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,76 +14,18 @@
|
|||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use core_foundation::base::ToVoid;
|
use security_framework::key::SecKey;
|
||||||
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 tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
use native_pkcs11_traits::{KeyAlgorithm, PrivateKey, PublicKey, SignatureAlgorithm};
|
use native_pkcs11_traits::{Backend, KeyAlgorithm, PrivateKey, PublicKey, SignatureAlgorithm};
|
||||||
use native_pkcs11_traits::DigestType as P11DigestType;
|
|
||||||
use native_pkcs11_traits::Result as P11Result;
|
use native_pkcs11_traits::Result as P11Result;
|
||||||
|
|
||||||
use crate::Result;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Algorithm {
|
pub enum Algorithm {
|
||||||
RSA,
|
RSA,
|
||||||
ECC,
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct YubikeyPivPrivateKey {
|
pub struct YubikeyPivPrivateKey {
|
||||||
sec_key: SecKey,
|
sec_key: SecKey,
|
||||||
@@ -94,22 +36,22 @@ pub struct YubikeyPivPrivateKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl YubikeyPivPrivateKey {
|
impl YubikeyPivPrivateKey {
|
||||||
#[instrument]
|
// #[instrument]
|
||||||
pub fn new(
|
// pub fn new(
|
||||||
sec_key: SecKey,
|
// sec_key: SecKey,
|
||||||
label: impl Into<String> + Debug,
|
// label: impl Into<String> + Debug,
|
||||||
pub_key: Option<YubikeyPivPublicKey>,
|
// pub_key: Option<YubikeyPivPublicKey>,
|
||||||
) -> Result<Self> {
|
// ) -> Result<Self> {
|
||||||
let label = label.into();
|
// let label = label.into();
|
||||||
let public_key_hash = sec_key.application_label().ok_or("no application_label")?;
|
// let public_key_hash = sec_key.application_label().ok_or("no application_label")?;
|
||||||
Ok(Self {
|
// Ok(Self {
|
||||||
algorithm: sec_key_algorithm(&sec_key)?,
|
// algorithm: sec_key_algorithm(&sec_key)?,
|
||||||
sec_key,
|
// sec_key,
|
||||||
label,
|
// label,
|
||||||
public_key_hash,
|
// public_key_hash,
|
||||||
pub_key,
|
// pub_key,
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrivateKey for YubikeyPivPrivateKey {
|
impl PrivateKey for YubikeyPivPrivateKey {
|
||||||
@@ -129,62 +71,38 @@ impl PrivateKey for YubikeyPivPrivateKey {
|
|||||||
algorithm: &SignatureAlgorithm,
|
algorithm: &SignatureAlgorithm,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> P11Result<Vec<u8>> {
|
) -> P11Result<Vec<u8>> {
|
||||||
let algorithm = sigalg_to_seckeyalg(algorithm)?;
|
match algorithm {
|
||||||
Ok(self.sec_key.create_signature(algorithm, data.as_ref())?)
|
SignatureAlgorithm::Ecdsa => {}
|
||||||
|
SignatureAlgorithm::RsaRaw => {}
|
||||||
|
SignatureAlgorithm::RsaPkcs1v15Raw => {}
|
||||||
|
SignatureAlgorithm::RsaPkcs1v15Sha1 => {}
|
||||||
|
SignatureAlgorithm::RsaPkcs1v15Sha384 => {}
|
||||||
|
SignatureAlgorithm::RsaPkcs1v15Sha256 => {}
|
||||||
|
SignatureAlgorithm::RsaPkcs1v15Sha512 => {}
|
||||||
|
SignatureAlgorithm::RsaPss { .. } => {}
|
||||||
|
}
|
||||||
|
// TODO sign data or hash??
|
||||||
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument]
|
||||||
fn delete(&self) {
|
fn delete(&self) {
|
||||||
let _ = self.sec_key.delete();
|
// yubikey-piv-pkcs11 just cannot delete private key
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument]
|
||||||
fn algorithm(&self) -> KeyAlgorithm {
|
fn algorithm(&self) -> KeyAlgorithm {
|
||||||
self.algorithm
|
self.algorithm
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_public_key(
|
fn find_public_key(
|
||||||
&self,
|
&self,
|
||||||
_backend: &dyn native_pkcs11_traits::Backend,
|
_backend: &dyn Backend,
|
||||||
) -> P11Result<Option<Box<dyn PublicKey>>> {
|
) -> P11Result<Option<Box<dyn PublicKey>>> {
|
||||||
let sec_copy = self
|
Ok(None)
|
||||||
.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 _))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct YubikeyPivPublicKey {
|
pub struct YubikeyPivPublicKey {
|
||||||
pub sec_key: SecKey,
|
pub sec_key: SecKey,
|
||||||
@@ -195,20 +113,20 @@ pub struct YubikeyPivPublicKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl YubikeyPivPublicKey {
|
impl YubikeyPivPublicKey {
|
||||||
#[instrument]
|
// #[instrument]
|
||||||
pub fn new(sec_key: SecKey, label: impl Into<String> + Debug) -> Result<Self> {
|
// pub fn new(sec_key: SecKey, label: impl Into<String> + Debug) -> Result<Self> {
|
||||||
let der = sec_key
|
// let der = sec_key
|
||||||
.external_representation()
|
// .external_representation()
|
||||||
.ok_or("no external representation")?;
|
// .ok_or("no external representation")?;
|
||||||
let key_ty = sec_key_algorithm(&sec_key)?;
|
// let key_ty = sec_key_algorithm(&sec_key)?;
|
||||||
Ok(Self {
|
// Ok(Self {
|
||||||
public_key_hash: sec_key.application_label().ok_or("no application_label")?,
|
// public_key_hash: sec_key.application_label().ok_or("no application_label")?,
|
||||||
sec_key,
|
// sec_key,
|
||||||
label: label.into(),
|
// label: label.into(),
|
||||||
der: der.to_vec(),
|
// der: der.to_vec(),
|
||||||
algorithm: key_ty,
|
// algorithm: key_ty,
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PublicKey for YubikeyPivPublicKey {
|
impl PublicKey for YubikeyPivPublicKey {
|
||||||
@@ -230,15 +148,15 @@ impl PublicKey for YubikeyPivPublicKey {
|
|||||||
#[instrument]
|
#[instrument]
|
||||||
fn verify(
|
fn verify(
|
||||||
&self,
|
&self,
|
||||||
algorithm: &native_pkcs11_traits::SignatureAlgorithm,
|
algorithm: &SignatureAlgorithm,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
signature: &[u8],
|
signature: &[u8],
|
||||||
) -> P11Result<()> {
|
) -> P11Result<()> {
|
||||||
let algorithm = sigalg_to_seckeyalg(algorithm)?;
|
// let algorithm = sigalg_to_seckeyalg(algorithm)?;
|
||||||
let result = self.sec_key.verify_signature(algorithm, data, signature)?;
|
// let result = self.sec_key.verify_signature(algorithm, data, signature)?;
|
||||||
if !result {
|
// if !result {
|
||||||
return Err("verify failed")?;
|
// return Err("verify failed")?;
|
||||||
}
|
// }
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,77 +168,3 @@ impl PublicKey for YubikeyPivPublicKey {
|
|||||||
self.algorithm
|
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)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,14 +12,14 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// 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 thiserror::Error;
|
||||||
use tracing_error::SpanTrace;
|
use tracing_error::SpanTrace;
|
||||||
|
|
||||||
|
pub use backend::YubikeyPivBackend;
|
||||||
|
use native_pkcs11_traits::SignatureAlgorithm;
|
||||||
|
|
||||||
mod backend;
|
mod backend;
|
||||||
pub mod certificate;
|
pub mod certificate;
|
||||||
pub mod key;
|
pub mod key;
|
||||||
@@ -32,7 +32,7 @@ pub struct Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for 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)?;
|
writeln!(f, "{:?}", self.error)?;
|
||||||
self.context.fmt(f)
|
self.context.fmt(f)
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ impl<E: Into<ErrorKind>> From<E> for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display 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)?;
|
writeln!(f, "{}", self.error)?;
|
||||||
std::fmt::Display::fmt(&self.context, f)
|
std::fmt::Display::fmt(&self.context, f)
|
||||||
}
|
}
|
||||||
@@ -80,12 +80,6 @@ pub enum ErrorKind {
|
|||||||
UnsupportedSignatureAlgorithm(SignatureAlgorithm),
|
UnsupportedSignatureAlgorithm(SignatureAlgorithm),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CFError> for ErrorKind {
|
|
||||||
fn from(e: CFError) -> Self {
|
|
||||||
ErrorKind::SecurityFramework(security_framework::base::Error::from_code(e.code() as i32))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for ErrorKind {
|
impl From<&str> for ErrorKind {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &str) -> Self {
|
||||||
ErrorKind::Generic(s.to_string())
|
ErrorKind::Generic(s.to_string())
|
||||||
|
|||||||
Reference in New Issue
Block a user