feat: init commit,fork from google native-pkcs11

This commit is contained in:
2024-07-06 19:06:25 +08:00
parent 27039d66bb
commit 33f33d2aa6
43 changed files with 34868 additions and 10 deletions

View File

@@ -0,0 +1,214 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::{ffi::CString, fmt::Debug, sync::Arc};
use native_pkcs11_traits::{
backend,
Certificate,
CertificateExt,
KeyAlgorithm,
PrivateKey,
PublicKey,
};
use p256::pkcs8::{
der::{asn1::OctetString, Encode},
AssociatedOid,
};
use pkcs1::{der::Decode, RsaPublicKey};
use pkcs11_sys::{
CKC_X_509,
CKK_EC,
CKK_RSA,
CKO_CERTIFICATE,
CKO_PRIVATE_KEY,
CKO_PROFILE,
CKO_PUBLIC_KEY,
CK_CERTIFICATE_CATEGORY_UNSPECIFIED,
CK_PROFILE_ID,
};
use tracing::debug;
use crate::attribute::{Attribute, AttributeType, Attributes};
#[derive(Debug)]
pub struct DataObject {
pub application: CString,
pub label: String,
pub value: Vec<u8>,
}
// Usage of generics is a workaround for the following issue:
// https://github.com/rust-lang/rust/issues/78808#issuecomment-1664416547
#[derive(Debug, PartialEq, Hash, Eq)]
pub enum Object<
DynCertificate: ?Sized + PartialEq = dyn Certificate,
DynPrivateKey: ?Sized + PartialEq = dyn PrivateKey,
DynPublicKey: ?Sized + PartialEq = dyn PublicKey,
> {
Certificate(Arc<DynCertificate>),
PrivateKey(Arc<DynPrivateKey>),
Profile(CK_PROFILE_ID),
PublicKey(Arc<DynPublicKey>),
}
impl Clone for Object {
fn clone(&self) -> Self {
match self {
Object::Certificate(cert) => Object::Certificate(cert.clone()),
Object::PrivateKey(private_key) => Object::PrivateKey(private_key.clone()),
Object::Profile(id) => Object::Profile(*id),
Object::PublicKey(public_key) => Object::PublicKey(public_key.clone()),
}
}
}
impl Object {
pub fn attribute(&self, type_: AttributeType) -> Option<Attribute> {
match self {
Object::Certificate(cert) => match type_ {
AttributeType::CertificateCategory => Some(Attribute::CertificateCategory(
CK_CERTIFICATE_CATEGORY_UNSPECIFIED,
)),
AttributeType::CertificateType => Some(Attribute::CertificateType(CKC_X_509)),
AttributeType::Class => Some(Attribute::Class(CKO_CERTIFICATE)),
AttributeType::Id => Some(Attribute::Id(cert.public_key().public_key_hash())),
AttributeType::Issuer => Some(Attribute::Issuer(cert.issuer())),
AttributeType::Label => Some(Attribute::Label(cert.label())),
AttributeType::Token => Some(Attribute::Token(true)),
AttributeType::Trusted => Some(Attribute::Trusted(false)),
AttributeType::SerialNumber => Some(Attribute::SerialNumber(cert.serial_number())),
AttributeType::Subject => Some(Attribute::Subject(cert.subject())),
AttributeType::Value => Some(Attribute::Value(cert.to_der())),
_ => {
debug!("certificate: type_ unimplemented: {:?}", type_);
None
}
},
Object::PrivateKey(private_key) => match type_ {
AttributeType::AlwaysSensitive => Some(Attribute::AlwaysSensitive(true)),
AttributeType::AlwaysAuthenticate => Some(Attribute::AlwaysAuthenticate(false)),
AttributeType::Class => Some(Attribute::Class(CKO_PRIVATE_KEY)),
AttributeType::Decrypt => Some(Attribute::Decrypt(false)),
AttributeType::EcParams => {
Some(Attribute::EcParams(p256::NistP256::OID.to_der().ok()?))
}
AttributeType::Extractable => Some(Attribute::Extractable(false)),
AttributeType::Id => Some(Attribute::Id(private_key.public_key_hash())),
AttributeType::KeyType => Some(Attribute::KeyType(match private_key.algorithm() {
native_pkcs11_traits::KeyAlgorithm::Rsa => CKK_RSA,
native_pkcs11_traits::KeyAlgorithm::Ecc => CKK_EC,
})),
AttributeType::Label => Some(Attribute::Label(private_key.label())),
AttributeType::Modulus => {
let modulus = private_key
.find_public_key(backend())
.ok()
.flatten()
.and_then(|public_key| {
let der = public_key.to_der();
RsaPublicKey::from_der(&der)
.map(|pk| pk.modulus.as_bytes().to_vec())
.ok()
});
modulus.map(Attribute::Modulus)
}
AttributeType::NeverExtractable => Some(Attribute::NeverExtractable(true)),
AttributeType::Private => Some(Attribute::Private(true)),
AttributeType::PublicExponent => {
let public_exponent = private_key
.find_public_key(backend())
.ok()
.flatten()
.and_then(|public_key| {
let der = public_key.to_der();
RsaPublicKey::from_der(&der)
.map(|pk| pk.public_exponent.as_bytes().to_vec())
.ok()
});
public_exponent.map(Attribute::PublicExponent)
}
AttributeType::Sensitive => Some(Attribute::Sensitive(true)),
AttributeType::Sign => Some(Attribute::Sign(true)),
AttributeType::SignRecover => Some(Attribute::SignRecover(false)),
AttributeType::Token => Some(Attribute::Token(true)),
AttributeType::Unwrap => Some(Attribute::Unwrap(false)),
_ => {
debug!("private_key: type_ unimplemented: {:?}", type_);
None
}
},
Object::Profile(id) => match type_ {
AttributeType::Class => Some(Attribute::Class(CKO_PROFILE)),
AttributeType::ProfileId => Some(Attribute::ProfileId(*id)),
AttributeType::Token => Some(Attribute::Token(true)),
_ => {
debug!("profile: type_ unimplemented: {:?}", type_);
None
}
},
Object::PublicKey(pk) => match type_ {
AttributeType::Class => Some(Attribute::Class(CKO_PUBLIC_KEY)),
AttributeType::Label => Some(Attribute::Label(pk.label())),
AttributeType::Modulus => {
let key = pk.to_der();
let key = RsaPublicKey::from_der(&key).unwrap();
Some(Attribute::Modulus(key.modulus.as_bytes().to_vec()))
}
AttributeType::PublicExponent => {
let key = pk.to_der();
let key = RsaPublicKey::from_der(&key).unwrap();
Some(Attribute::Modulus(key.public_exponent.as_bytes().to_vec()))
}
AttributeType::KeyType => Some(Attribute::KeyType(match pk.algorithm() {
native_pkcs11_traits::KeyAlgorithm::Rsa => CKK_RSA,
native_pkcs11_traits::KeyAlgorithm::Ecc => CKK_EC,
})),
AttributeType::Id => Some(Attribute::Id(pk.public_key_hash())),
AttributeType::EcPoint => {
if pk.algorithm() != KeyAlgorithm::Ecc {
return None;
}
let wrapped = OctetString::new(pk.to_der()).ok()?;
Some(Attribute::EcPoint(wrapped.to_der().ok()?))
}
AttributeType::EcParams => {
Some(Attribute::EcParams(p256::NistP256::OID.to_der().ok()?))
}
_ => {
debug!("public_key: type_ unimplemented: {:?}", type_);
None
}
},
}
}
pub fn matches(&self, others: &Attributes) -> bool {
if let Some(class) = others.get(AttributeType::Class) {
if *class != self.attribute(AttributeType::Class).unwrap() {
return false;
}
}
for other in others {
if let Some(attr) = self.attribute(other.attribute_type()) {
if *other != attr {
return false;
}
} else {
return false;
}
}
true
}
}