use alloc::boxed::Box;
use alloc::vec::Vec;
use core::fmt::Debug;
use pki_types::{AlgorithmIdentifier, CertificateDer, PrivateKeyDer, SubjectPublicKeyInfoDer};
use super::CryptoProvider;
use crate::client::ResolvesClientCert;
use crate::enums::{SignatureAlgorithm, SignatureScheme};
use crate::error::{Error, InconsistentKeys};
use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert};
use crate::sync::Arc;
use crate::x509;
pub trait SigningKey: Debug + Send + Sync {
fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>>;
fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> {
None
}
fn algorithm(&self) -> SignatureAlgorithm;
}
pub trait Signer: Debug + Send + Sync {
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error>;
fn scheme(&self) -> SignatureScheme;
}
#[derive(Debug)]
pub struct SingleCertAndKey(Arc<CertifiedKey>);
impl From<CertifiedKey> for SingleCertAndKey {
fn from(certified_key: CertifiedKey) -> Self {
Self(Arc::new(certified_key))
}
}
impl From<Arc<CertifiedKey>> for SingleCertAndKey {
fn from(certified_key: Arc<CertifiedKey>) -> Self {
Self(certified_key)
}
}
impl ResolvesClientCert for SingleCertAndKey {
fn resolve(
&self,
_root_hint_subjects: &[&[u8]],
_sigschemes: &[SignatureScheme],
) -> Option<Arc<CertifiedKey>> {
Some(self.0.clone())
}
fn has_certs(&self) -> bool {
true
}
}
impl ResolvesServerCert for SingleCertAndKey {
fn resolve(&self, _client_hello: ClientHello<'_>) -> Option<Arc<CertifiedKey>> {
Some(self.0.clone())
}
}
#[derive(Clone, Debug)]
pub struct CertifiedKey {
pub cert: Vec<CertificateDer<'static>>,
pub key: Arc<dyn SigningKey>,
pub ocsp: Option<Vec<u8>>,
}
impl CertifiedKey {
pub fn from_der(
cert_chain: Vec<CertificateDer<'static>>,
key: PrivateKeyDer<'static>,
provider: &CryptoProvider,
) -> Result<Self, Error> {
let private_key = provider
.key_provider
.load_private_key(key)?;
let certified_key = Self::new(cert_chain, private_key);
match certified_key.keys_match() {
Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => Ok(certified_key),
Err(err) => Err(err),
}
}
pub fn new(cert: Vec<CertificateDer<'static>>, key: Arc<dyn SigningKey>) -> Self {
Self {
cert,
key,
ocsp: None,
}
}
pub fn keys_match(&self) -> Result<(), Error> {
let Some(key_spki) = self.key.public_key() else {
return Err(InconsistentKeys::Unknown.into());
};
let cert = ParsedCertificate::try_from(self.end_entity_cert()?)?;
match key_spki == cert.subject_public_key_info() {
true => Ok(()),
false => Err(InconsistentKeys::KeyMismatch.into()),
}
}
pub fn end_entity_cert(&self) -> Result<&CertificateDer<'_>, Error> {
self.cert
.first()
.ok_or(Error::NoCertificatesPresented)
}
}
pub fn public_key_to_spki(
alg_id: &AlgorithmIdentifier,
public_key: impl AsRef<[u8]>,
) -> SubjectPublicKeyInfoDer<'static> {
let mut spki_inner = x509::wrap_in_sequence(alg_id.as_ref());
spki_inner.extend(&x509::wrap_in_bit_string(public_key.as_ref()));
let spki = x509::wrap_in_sequence(&spki_inner);
SubjectPublicKeyInfoDer::from(spki)
}