use alloc::boxed::Box;
use alloc::vec::Vec;
#[cfg(feature = "std")]
use super::config::SigningKey;
use super::error::Error;
pub trait PrivateKey: Send + Sync {
fn schemes(&self) -> Vec<u16>;
fn start_sign(&self, scheme: u16, message: &[u8]) -> Result<Box<dyn SignOp>, Error>;
}
pub trait SignOp: Send {
fn resume(&mut self) -> Result<SignProgress, Error>;
fn readiness(&self) -> Option<Readiness> {
None
}
}
pub enum SignProgress {
Pending,
Done(Vec<u8>),
}
#[derive(Clone, Copy)]
pub struct Readiness {
#[cfg(all(feature = "std", unix))]
fd: core::ffi::c_int,
}
impl Readiness {
#[cfg(all(feature = "std", unix))]
pub fn from_raw_fd(fd: core::ffi::c_int) -> Self {
Readiness { fd }
}
#[cfg(feature = "std")]
pub fn wait(&self) -> std::io::Result<()> {
#[cfg(unix)]
{
let want = sys::POLLIN | sys::POLLPRI | sys::POLLERR | sys::POLLHUP;
loop {
let mut pfd = sys::Pollfd {
fd: self.fd,
events: want,
revents: 0,
};
#[allow(unsafe_code)]
let rc = unsafe { sys::poll(&mut pfd as *mut sys::Pollfd, 1, -1) };
if rc < 0 {
let err = std::io::Error::last_os_error();
if err.kind() == std::io::ErrorKind::Interrupted {
continue;
}
return Err(err);
}
return Ok(());
}
}
#[cfg(not(unix))]
{
Ok(())
}
}
}
#[cfg(all(feature = "std", unix))]
impl std::os::fd::AsRawFd for Readiness {
fn as_raw_fd(&self) -> std::os::fd::RawFd {
self.fd
}
}
#[cfg(all(feature = "std", unix))]
impl std::os::fd::AsFd for Readiness {
fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
#[allow(unsafe_code)]
unsafe {
std::os::fd::BorrowedFd::borrow_raw(self.fd)
}
}
}
#[cfg(all(feature = "std", unix))]
mod sys {
#![allow(unsafe_code)]
use core::ffi::c_int;
#[cfg(target_os = "linux")]
pub(super) type NfdsT = core::ffi::c_ulong;
#[cfg(not(target_os = "linux"))]
pub(super) type NfdsT = core::ffi::c_uint;
pub(super) const POLLIN: core::ffi::c_short = 0x0001;
pub(super) const POLLPRI: core::ffi::c_short = 0x0002;
pub(super) const POLLERR: core::ffi::c_short = 0x0008;
pub(super) const POLLHUP: core::ffi::c_short = 0x0010;
#[repr(C)]
pub(super) struct Pollfd {
pub(super) fd: c_int,
pub(super) events: core::ffi::c_short,
pub(super) revents: core::ffi::c_short,
}
unsafe extern "C" {
pub(super) fn poll(fds: *mut Pollfd, nfds: NfdsT, timeout: c_int) -> c_int;
}
}
#[cfg(feature = "std")]
pub struct LocalSigner {
key: SigningKey,
}
#[cfg(feature = "std")]
impl LocalSigner {
pub fn new(key: SigningKey) -> Self {
LocalSigner { key }
}
}
#[cfg(feature = "std")]
impl PrivateKey for LocalSigner {
fn schemes(&self) -> Vec<u16> {
let server_key = self.key.to_server_key_13();
alloc::vec![super::crypto::signature_scheme_for(&server_key).0]
}
fn start_sign(&self, _scheme: u16, message: &[u8]) -> Result<Box<dyn SignOp>, Error> {
let server_key = self.key.to_server_key_13();
let (_scheme, sig) =
super::crypto::sign_certificate_verify(&server_key, message, &mut crate::rng::OsRng)?;
Ok(Box::new(ReadySignOp { sig: Some(sig) }))
}
}
#[cfg(feature = "std")]
struct ReadySignOp {
sig: Option<Vec<u8>>,
}
#[cfg(feature = "std")]
impl SignOp for ReadySignOp {
fn resume(&mut self) -> Result<SignProgress, Error> {
match self.sig.take() {
Some(sig) => Ok(SignProgress::Done(sig)),
None => Err(Error::InappropriateState),
}
}
}