#![forbid(unsafe_code)]
use std::sync::atomic::{AtomicBool, Ordering};
use crate::errors::SshCliResult;
static PROVIDER_READY: AtomicBool = AtomicBool::new(false);
pub const PROVIDER_NAME: &str = "aws_lc_rs";
pub fn install_default_provider() -> SshCliResult<()> {
if PROVIDER_READY.load(Ordering::Acquire) {
return Ok(());
}
if rustls::crypto::CryptoProvider::get_default().is_some() {
PROVIDER_READY.store(true, Ordering::Release);
return Ok(());
}
match rustls::crypto::aws_lc_rs::default_provider().install_default() {
Ok(()) => {
PROVIDER_READY.store(true, Ordering::Release);
tracing::debug!(provider = PROVIDER_NAME, "rustls CryptoProvider installed");
Ok(())
}
Err(_already) => {
PROVIDER_READY.store(true, Ordering::Release);
tracing::debug!(
provider = PROVIDER_NAME,
"rustls CryptoProvider already installed by another caller"
);
Ok(())
}
}
}
#[must_use]
pub fn provider_is_installed() -> bool {
PROVIDER_READY.load(Ordering::Acquire)
|| rustls::crypto::CryptoProvider::get_default().is_some()
}
#[must_use]
pub fn provider_name() -> &'static str {
PROVIDER_NAME
}
pub(crate) fn ensure_provider() -> SshCliResult<()> {
install_default_provider()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn install_is_idempotent() {
install_default_provider().expect("first");
install_default_provider().expect("second");
assert!(provider_is_installed());
assert_eq!(provider_name(), "aws_lc_rs");
}
}