use crate::errors::RtcResult as Result;
use alloc::boxed::Box;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::sync::atomic::{AtomicPtr, Ordering};
pub trait SigningKey: Send + Sync {
fn sign(&self, msg: &[u8]) -> Result<Vec<u8>>;
fn verifying_key(&self) -> Result<Box<dyn VerifyingKey>>;
}
pub trait VerifyingKey: Send + Sync {
fn verify(&self, msg: &[u8], signature_der: &[u8]) -> Result<()>;
}
pub trait EcdhSecret: Send + Sync {
fn shared_secret(&self, peer_public: &[u8]) -> Result<Vec<u8>>;
}
pub trait DtlsCrypto: Send + Sync + 'static {
fn signing_key_from_pkcs8_der(&self, der: &[u8]) -> Result<Box<dyn SigningKey>>;
fn verifying_key_from_point(&self, point: &[u8]) -> Result<Box<dyn VerifyingKey>>;
fn ecdh_generate(&self) -> Result<(Vec<u8>, Box<dyn EcdhSecret>)>;
}
static CRYPTO: AtomicPtr<Arc<dyn DtlsCrypto>> = AtomicPtr::new(core::ptr::null_mut());
pub fn set_crypto(impl_: Arc<dyn DtlsCrypto>) {
let leaked = alloc::boxed::Box::leak(alloc::boxed::Box::new(impl_));
CRYPTO.store(leaked as *mut Arc<dyn DtlsCrypto>, Ordering::Release);
}
pub fn crypto() -> &'static dyn DtlsCrypto {
let ptr = CRYPTO.load(Ordering::Acquire);
if !ptr.is_null() {
return unsafe { &**ptr };
}
#[cfg(feature = "crypto-p256")]
{
static REFERENCE: crate::platform::crypto_p256::P256Crypto =
crate::platform::crypto_p256::P256Crypto;
return &REFERENCE;
}
#[cfg(not(feature = "crypto-p256"))]
panic!(
"no DTLS crypto backend: enable the `crypto-p256` feature or call \
platform::crypto::set_crypto before handshaking"
);
}
#[cfg(feature = "crypto-p256")]
pub use crate::platform::crypto_p256::PlatformRng;