b8ce58ddf0
aura-crypto: X25519 + ML-KEM-768 (FIPS 203) hybrid KEM, HKDF-SHA256 session key derivation, ChaCha20-Poly1305 AeadSession with counter nonces; genuine NIST ACVP ML-KEM-768 KAT (decapsulation vector). 16 tests green, clippy clean. aura-pki: self-signed CA, server/client cert issuance (rcgen 0.14), mutual X.509 chain verification via rustls-webpki, CRL revocation. 8 tests green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
54 lines
1.9 KiB
Rust
54 lines
1.9 KiB
Rust
//! aura-pki — mutual X.509 authentication for the Aura VPN.
|
|
//!
|
|
//! A self-signed Aura CA ([`AuraCa`]) issues a server certificate (carrying a
|
|
//! DNS SAN) and per-client certificates (`CN = client_id`). The server verifies
|
|
//! client certificates against the CA and the client verifies the server
|
|
//! certificate against the CA via [`AuraCertVerifier`]. v1 revocation is a
|
|
//! simple CRL: a set of revoked certificate serials or client ids, see
|
|
//! [`AuraCertVerifier::set_revoked`] and [`CrlStore`].
|
|
//!
|
|
//! Certificates use ECDSA P-256 / SHA-256 keys (rcgen's default), and chain
|
|
//! verification is performed with `rustls-webpki` against the CA trust anchor.
|
|
|
|
mod ca;
|
|
mod cert;
|
|
mod store;
|
|
|
|
pub use ca::{AuraCa, IssuedCert};
|
|
pub use cert::AuraCertVerifier;
|
|
pub use store::CrlStore;
|
|
|
|
/// Errors produced by the Aura PKI.
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum PkiError {
|
|
/// A PEM/DER blob could not be parsed into a certificate.
|
|
#[error("failed to parse certificate: {0}")]
|
|
CertParse(String),
|
|
|
|
/// The supplied certificate chain was empty.
|
|
#[error("empty certificate chain")]
|
|
EmptyChain,
|
|
|
|
/// The trust anchor (CA certificate) could not be constructed.
|
|
#[error("invalid trust anchor: {0}")]
|
|
TrustAnchor(String),
|
|
|
|
/// Chain verification against the CA failed (bad signature, expired,
|
|
/// untrusted issuer, wrong key usage, ...).
|
|
#[error("certificate chain verification failed: {0}")]
|
|
Verification(String),
|
|
|
|
/// The server certificate is not valid for the requested name.
|
|
#[error("certificate is not valid for name '{0}'")]
|
|
NameMismatch(String),
|
|
|
|
/// The end-entity certificate did not contain the expected identity, e.g. a
|
|
/// client certificate without a Common Name.
|
|
#[error("missing identity in certificate: {0}")]
|
|
MissingIdentity(String),
|
|
|
|
/// The certificate was found in the revocation list.
|
|
#[error("certificate is revoked: {0}")]
|
|
Revoked(String),
|
|
}
|