saml_rs/crypto/
provider.rs1use std::fmt;
4
5use crate::error::SamlError;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9#[non_exhaustive]
10pub enum CryptoProvider {
11 RustCrypto,
13 AwsLc,
15}
16
17impl fmt::Display for CryptoProvider {
18 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
19 formatter.write_str(match self {
20 Self::RustCrypto => "rustcrypto",
21 Self::AwsLc => "aws-lc",
22 })
23 }
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28#[non_exhaustive]
29pub enum CryptoFipsStatus {
30 Disabled,
32 Uninitialized,
34 Active,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
40#[non_exhaustive]
41pub struct CryptoProviderInfo {
42 provider: CryptoProvider,
43 fips: CryptoFipsStatus,
44}
45
46impl CryptoProviderInfo {
47 #[must_use]
49 pub const fn provider(&self) -> CryptoProvider {
50 self.provider
51 }
52
53 #[must_use]
55 pub const fn fips_status(&self) -> CryptoFipsStatus {
56 self.fips
57 }
58}
59
60fn provider_info(info: bergshamra::BackendInfo) -> CryptoProviderInfo {
61 let provider = match info.document {
62 bergshamra::BackendId::RustCrypto => CryptoProvider::RustCrypto,
63 bergshamra::BackendId::AwsLc => CryptoProvider::AwsLc,
64 };
65 let fips = match info.fips {
66 bergshamra::FipsStatus::Disabled => CryptoFipsStatus::Disabled,
67 bergshamra::FipsStatus::Uninitialized => CryptoFipsStatus::Uninitialized,
68 bergshamra::FipsStatus::Active => CryptoFipsStatus::Active,
69 };
70 CryptoProviderInfo { provider, fips }
71}
72
73fn provider_error(action: &str, error: impl fmt::Display) -> SamlError {
74 SamlError::Crypto(format!("crypto provider {action} failed: {error}"))
75}
76
77pub fn crypto_provider_info() -> Result<CryptoProviderInfo, SamlError> {
86 bergshamra::backend_info()
87 .map(provider_info)
88 .map_err(|error| provider_error("inspection", error))
89}
90
91pub fn initialize_crypto_provider() -> Result<CryptoProviderInfo, SamlError> {
103 bergshamra::initialize_backend()
104 .map(provider_info)
105 .map_err(|error| provider_error("initialization", error))
106}
107
108pub(crate) fn ensure_crypto_provider_initialized() -> Result<(), SamlError> {
109 initialize_crypto_provider().map(|_| ())
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn initialization_reports_selected_provider() -> Result<(), Box<dyn std::error::Error>> {
118 let info = initialize_crypto_provider()?;
119
120 #[cfg(feature = "crypto-rustcrypto")]
121 assert_eq!(info.provider(), CryptoProvider::RustCrypto);
122 #[cfg(any(feature = "crypto-aws-lc", feature = "crypto-fips"))]
123 assert_eq!(info.provider(), CryptoProvider::AwsLc);
124
125 Ok(())
126 }
127
128 #[cfg(not(feature = "crypto-fips"))]
129 #[test]
130 fn initialization_reports_fips_disabled_without_fips_feature(
131 ) -> Result<(), Box<dyn std::error::Error>> {
132 let info = initialize_crypto_provider()?;
133
134 assert_eq!(info.fips_status(), CryptoFipsStatus::Disabled);
135 Ok(())
136 }
137
138 #[cfg(feature = "crypto-fips")]
139 #[test]
140 fn initialization_attests_active_fips_mode() -> Result<(), Box<dyn std::error::Error>> {
141 let info = initialize_crypto_provider()?;
142
143 assert_eq!(info.fips_status(), CryptoFipsStatus::Active);
144 Ok(())
145 }
146}