libcrux_traits/ecdh/
arrayref.rs

1//! This module contains the trait and related errors for an ECDH
2//! implementation that takes array references as arguments and writes
3//! outputs to mutable array references.
4
5use libcrux_secrets::U8;
6
7/// An Elliptic Curve Diffie-Hellman (ECDH) key exchange. This trait is the most low-level and mostly used in the
8/// implementation of other, more usabe APIs on top.
9pub trait EcdhArrayref<const RAND_LEN: usize, const SECRET_LEN: usize, const PUBLIC_LEN: usize> {
10    /// Generate a Diffie-Hellman secret value.
11    /// It is the responsibility of the caller to ensure  that the `rand` argument is actually
12    /// random.
13    fn generate_secret(
14        secret: &mut [U8; SECRET_LEN],
15        rand: &[U8; RAND_LEN],
16    ) -> Result<(), GenerateSecretError>;
17
18    /// Derive a Diffie-Hellman public value from a secret value.
19    fn secret_to_public(
20        public: &mut [u8; PUBLIC_LEN],
21        secret: &[U8; SECRET_LEN],
22    ) -> Result<(), SecretToPublicError>;
23
24    /// Generate a Diffie-Hellman secret value and derive the
25    /// corresponding public value in one step.
26    fn generate_pair(
27        public: &mut [u8; PUBLIC_LEN],
28        secret: &mut [U8; SECRET_LEN],
29        rand: &[U8; RAND_LEN],
30    ) -> Result<(), GenerateSecretError> {
31        Self::generate_secret(secret, rand)?;
32        Self::secret_to_public(public, secret).map_err(|_| GenerateSecretError::Unknown)
33    }
34
35    /// Derive a Diffie-Hellman shared secret from a public and a
36    /// secret value.
37    ///
38    /// This value is NOT (!) safe for use as a key and needs to be processed in a round of key
39    /// derivation, to ensure both that the output is uniformly random and that unkown key share
40    /// attacks can not happen.
41    fn derive_ecdh(
42        derived: &mut [U8; PUBLIC_LEN],
43        public: &[u8; PUBLIC_LEN],
44        secret: &[U8; SECRET_LEN],
45    ) -> Result<(), DeriveError>;
46
47    /// Check the validity of a Diffie-Hellman secret value.
48    fn validate_secret(secret: &[U8; SECRET_LEN]) -> Result<(), ValidateSecretError>;
49}
50
51#[derive(Debug)]
52/// An error during secret value generation.
53pub enum GenerateSecretError {
54    /// Error generating secret value with provided randomness
55    InvalidRandomness,
56
57    /// An unknown error occurred
58    Unknown,
59}
60
61#[derive(Debug)]
62/// An error during derivation of a public value from a secret value.
63pub enum SecretToPublicError {
64    /// Secret value was invalid
65    InvalidSecret,
66    /// An unknown error occurred
67    Unknown,
68}
69
70#[derive(Debug)]
71/// An error derivation of Diffie-Hellman shared secret.
72pub enum DeriveError {
73    /// Public value was invalid
74    InvalidPublic,
75    /// Secret value was invalid
76    InvalidSecret,
77    /// An unknown error occurred
78    Unknown,
79}
80
81#[derive(Debug)]
82/// A Diffie-Hellman secret value was found to be invalid.
83pub enum ValidateSecretError {
84    /// Secret value was invalid
85    InvalidSecret,
86    /// An unknown error occurred
87    Unknown,
88}
89
90impl core::fmt::Display for GenerateSecretError {
91    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
92        let text = match self {
93            GenerateSecretError::InvalidRandomness => {
94                "error generating secret value with provided randomness"
95            }
96            GenerateSecretError::Unknown => "an unknown error occured",
97        };
98
99        f.write_str(text)
100    }
101}
102
103impl core::fmt::Display for SecretToPublicError {
104    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
105        let text = match self {
106            SecretToPublicError::InvalidSecret => "secret value is invalid",
107            SecretToPublicError::Unknown => "an unknown error occured",
108        };
109
110        f.write_str(text)
111    }
112}
113
114impl core::fmt::Display for DeriveError {
115    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
116        let text = match self {
117            DeriveError::InvalidPublic => "public value is invalid",
118            DeriveError::InvalidSecret => "secret value is invalid",
119            DeriveError::Unknown => "an unknown error occured",
120        };
121
122        f.write_str(text)
123    }
124}
125
126impl core::fmt::Display for ValidateSecretError {
127    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
128        let text = match self {
129            ValidateSecretError::InvalidSecret => "secret value is invalid",
130            ValidateSecretError::Unknown => "an unknown error occured",
131        };
132
133        f.write_str(text)
134    }
135}
136
137#[cfg(feature = "error-in-core")]
138/// Here we implement the Error trait. This has only been added to core relatively recently, so we
139/// are hiding that behind a feature.
140mod error_in_core {
141    impl core::error::Error for super::GenerateSecretError {}
142    impl core::error::Error for super::SecretToPublicError {}
143    impl core::error::Error for super::DeriveError {}
144    impl core::error::Error for super::ValidateSecretError {}
145}