Skip to main content

confium_openssl_provider/
lib.rs

1//! OpenSSL 3.0 provider using Confium for signing.
2//!
3//! Allows OpenSSL applications (nginx, Apache, OpenSSH, etc.) to use
4//! Confium-backed threshold signing keys without code changes.
5//! Implements the OpenSSL 3.0 provider API (OSSL_OP_*).
6//!
7//! The provider is loaded via OpenSSL config or `OPENSSL_CONF` env var:
8//! ```text
9//! openssl_conf = openssl_init
10//!
11//! [openssl_init]
12//! providers = provider_sect
13//!
14//! [provider_sect]
15//! confium = confium_sect
16//!
17//! [confium_sect]
18//! activate = 1
19//! module = /usr/lib/confium/confium_openssl_provider.so
20//! ```
21//!
22//! See `TODO.roadmap/28-mode2-pki-replacement.md` for full spec.
23
24#![forbid(unsafe_code)]
25#![allow(missing_docs)] // TODO: document before 1.0
26
27use serde::{Deserialize, Serialize};
28
29/// Provider metadata reported to OpenSSL.
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct ProviderInfo {
32    /// Provider name (e.g., "confium").
33    pub name: String,
34    /// Provider version.
35    pub version: String,
36    /// Provider description.
37    pub description: String,
38    /// Build info.
39    pub buildinfo: String,
40}
41
42impl ProviderInfo {
43    /// Default Confium provider info.
44    pub fn default_confium() -> Self {
45        Self {
46            name: "confium".into(),
47            version: env!("CARGO_PKG_VERSION").into(),
48            description: "Confium threshold cryptography provider for OpenSSL 3.0".into(),
49            buildinfo: "Confium OpenSSL Provider".into(),
50        }
51    }
52}
53
54/// Operations supported by this provider (subset of OpenSSL OSSL_OP_*).
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
56#[serde(rename_all = "snake_case")]
57pub enum Operation {
58    /// Signature production.
59    Signer,
60    /// Signature verification.
61    Verifier,
62    /// Digest computation.
63    Digester,
64    /// Key generation.
65    KeyGenerator,
66    /// Key import/export.
67    KeyEncoder,
68    /// Key store.
69    StoreLoader,
70}
71
72impl Operation {
73    /// All operations supported by the Confium provider.
74    pub fn all() -> &'static [Operation] {
75        &[
76            Operation::Signer,
77            Operation::Verifier,
78            Operation::Digester,
79            Operation::KeyGenerator,
80            Operation::KeyEncoder,
81            Operation::StoreLoader,
82        ]
83    }
84}
85
86/// Algorithms supported (mapped to OpenSSL algorithm names).
87#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
88#[serde(rename_all = "snake_case")]
89pub enum Algorithm {
90    /// Ed25519 over Ed25519 curve.
91    Ed25519,
92    /// ECDSA over P-256.
93    EcdsaP256,
94    /// ECDSA over P-384.
95    EcdsaP384,
96    /// ML-DSA-65 (post-quantum).
97    MlDsa65,
98    /// Composite Ed25519 + ML-DSA-65.
99    CompositeEd25519MlDsa65,
100}
101
102impl Algorithm {
103    /// OpenSSL algorithm name for this algorithm.
104    pub fn openssl_name(&self) -> &'static str {
105        match self {
106            Algorithm::Ed25519 => "Ed25519",
107            Algorithm::EcdsaP256 => "ECDSA",
108            Algorithm::EcdsaP384 => "ECDSA",
109            Algorithm::MlDsa65 => "ML-DSA-65",
110            Algorithm::CompositeEd25519MlDsa65 => "composite-MLDSA65-Ed25519",
111        }
112    }
113}
114
115/// Provider configuration.
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct ProviderConfig {
118    /// Path to the Confium daemon socket.
119    pub daemon_socket: String,
120    /// Quorum to use by default.
121    pub default_quorum: String,
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127
128    #[test]
129    fn default_provider_info() {
130        let info = ProviderInfo::default_confium();
131        assert_eq!(info.name, "confium");
132    }
133
134    #[test]
135    fn all_operations_non_empty() {
136        assert!(!Operation::all().is_empty());
137    }
138
139    #[test]
140    fn ed25519_openssl_name() {
141        assert_eq!(Algorithm::Ed25519.openssl_name(), "Ed25519");
142    }
143}