use alloc::boxed::Box;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::fmt::Debug;
use pki_types::{AlgorithmIdentifier, CertificateDer, SubjectPublicKeyInfoDer};
use crate::enums::{SignatureAlgorithm, SignatureScheme};
use crate::error::{Error, InconsistentKeys};
use crate::server::ParsedCertificate;
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(Clone, Debug)]
pub struct CertifiedKey {
pub cert: Vec<CertificateDer<'static>>,
pub key: Arc<dyn SigningKey>,
pub ocsp: Option<Vec<u8>>,
}
impl CertifiedKey {
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 key_spki = match self.key.public_key() {
Some(key) => key,
None => 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)
}
}
#[cfg_attr(not(any(feature = "aws_lc_rs", feature = "ring")), allow(dead_code))]
pub(crate) 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)
}