ant_quic/crypto/pqc/
types.rs

1// Copyright 2024 Saorsa Labs Ltd.
2//
3// This Saorsa Network Software is licensed under the General Public License (GPL), version 3.
4// Please see the file LICENSE-GPL, or visit <http://www.gnu.org/licenses/> for the full text.
5//
6// Full details available at https://saorsalabs.com/licenses
7#![allow(missing_docs)]
8
9//! Type definitions for Post-Quantum Cryptography
10
11use serde::{Deserialize, Serialize};
12use thiserror::Error;
13use zeroize::{Zeroize, ZeroizeOnDrop};
14
15/// Result type for PQC operations
16pub type PqcResult<T> = Result<T, PqcError>;
17
18/// Errors that can occur during PQC operations
19#[derive(Debug, Error, Clone)]
20pub enum PqcError {
21    /// Invalid key size
22    #[error("Invalid key size: expected {expected}, got {actual}")]
23    InvalidKeySize { expected: usize, actual: usize },
24
25    /// Invalid ciphertext size
26    #[error("Invalid ciphertext size: expected {expected}, got {actual}")]
27    InvalidCiphertextSize { expected: usize, actual: usize },
28
29    /// Invalid ciphertext
30    #[error("Invalid ciphertext")]
31    InvalidCiphertext,
32
33    /// Invalid signature size
34    #[error("Invalid signature size: expected {expected}, got {actual}")]
35    InvalidSignatureSize { expected: usize, actual: usize },
36
37    /// Key generation failed
38    #[error("Key generation failed: {0}")]
39    KeyGenerationFailed(String),
40
41    /// Encapsulation failed
42    #[error("Encapsulation failed: {0}")]
43    EncapsulationFailed(String),
44
45    /// Decapsulation failed
46    #[error("Decapsulation failed: {0}")]
47    DecapsulationFailed(String),
48
49    /// Signing failed
50    #[error("Signing failed: {0}")]
51    SigningFailed(String),
52
53    /// Verification failed
54    #[error("Verification failed: {0}")]
55    VerificationFailed(String),
56
57    /// Feature not available
58    #[error("PQC feature not enabled")]
59    FeatureNotAvailable,
60
61    /// Generic cryptographic error
62    #[error("Cryptographic error: {0}")]
63    CryptoError(String),
64
65    /// Memory pool error
66    #[error("Memory pool error: {0}")]
67    PoolError(String),
68
69    /// Invalid public key
70    #[error("Invalid public key")]
71    InvalidPublicKey,
72
73    /// Invalid signature
74    #[error("Invalid signature")]
75    InvalidSignature,
76
77    /// Invalid secret key
78    #[error("Invalid secret key")]
79    InvalidSecretKey,
80
81    /// Invalid shared secret
82    #[error("Invalid shared secret")]
83    InvalidSharedSecret,
84
85    /// Operation not supported
86    #[error("Operation not supported")]
87    OperationNotSupported,
88
89    /// Negotiation failed
90    #[error("Negotiation failed: {0}")]
91    NegotiationFailed(String),
92
93    /// Key exchange failed
94    #[error("Key exchange failed")]
95    KeyExchangeFailed,
96}
97
98// ML-KEM-768 constants
99pub const ML_KEM_768_PUBLIC_KEY_SIZE: usize = 1184;
100pub const ML_KEM_768_SECRET_KEY_SIZE: usize = 2400;
101pub const ML_KEM_768_CIPHERTEXT_SIZE: usize = 1088;
102pub const ML_KEM_768_SHARED_SECRET_SIZE: usize = 32;
103
104// ML-DSA-65 constants
105pub const ML_DSA_65_PUBLIC_KEY_SIZE: usize = 1952;
106pub const ML_DSA_65_SECRET_KEY_SIZE: usize = 4032;
107pub const ML_DSA_65_SIGNATURE_SIZE: usize = 3309;
108
109/// ML-KEM-768 public key
110#[derive(Clone)]
111pub struct MlKemPublicKey(pub Box<[u8; ML_KEM_768_PUBLIC_KEY_SIZE]>);
112
113impl MlKemPublicKey {
114    /// Get the public key as bytes
115    pub fn as_bytes(&self) -> &[u8] {
116        &self.0[..]
117    }
118
119    /// Create from bytes
120    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PqcError> {
121        if bytes.len() != ML_KEM_768_PUBLIC_KEY_SIZE {
122            return Err(PqcError::InvalidKeySize {
123                expected: ML_KEM_768_PUBLIC_KEY_SIZE,
124                actual: bytes.len(),
125            });
126        }
127        let mut key = Box::new([0u8; ML_KEM_768_PUBLIC_KEY_SIZE]);
128        key.copy_from_slice(bytes);
129        Ok(Self(key))
130    }
131}
132
133impl Serialize for MlKemPublicKey {
134    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
135    where
136        S: serde::Serializer,
137    {
138        serializer.serialize_bytes(self.as_bytes())
139    }
140}
141
142impl<'de> Deserialize<'de> for MlKemPublicKey {
143    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
144    where
145        D: serde::Deserializer<'de>,
146    {
147        let bytes = <Vec<u8>>::deserialize(deserializer)?;
148        Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
149    }
150}
151
152/// ML-KEM-768 secret key
153#[derive(ZeroizeOnDrop)]
154pub struct MlKemSecretKey(pub Box<[u8; ML_KEM_768_SECRET_KEY_SIZE]>);
155
156impl Zeroize for MlKemSecretKey {
157    fn zeroize(&mut self) {
158        self.0.as_mut().zeroize();
159    }
160}
161
162impl MlKemSecretKey {
163    /// Get the secret key as bytes
164    pub fn as_bytes(&self) -> &[u8] {
165        &self.0[..]
166    }
167
168    /// Create from bytes
169    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PqcError> {
170        if bytes.len() != ML_KEM_768_SECRET_KEY_SIZE {
171            return Err(PqcError::InvalidKeySize {
172                expected: ML_KEM_768_SECRET_KEY_SIZE,
173                actual: bytes.len(),
174            });
175        }
176        let mut key = Box::new([0u8; ML_KEM_768_SECRET_KEY_SIZE]);
177        key.copy_from_slice(bytes);
178        Ok(Self(key))
179    }
180}
181
182impl Serialize for MlKemSecretKey {
183    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
184    where
185        S: serde::Serializer,
186    {
187        serializer.serialize_bytes(self.as_bytes())
188    }
189}
190
191impl<'de> Deserialize<'de> for MlKemSecretKey {
192    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
193    where
194        D: serde::Deserializer<'de>,
195    {
196        let bytes = <Vec<u8>>::deserialize(deserializer)?;
197        Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
198    }
199}
200
201/// ML-KEM-768 ciphertext
202#[derive(Clone)]
203pub struct MlKemCiphertext(pub Box<[u8; ML_KEM_768_CIPHERTEXT_SIZE]>);
204
205impl MlKemCiphertext {
206    /// Get the ciphertext as bytes
207    pub fn as_bytes(&self) -> &[u8] {
208        &self.0[..]
209    }
210
211    /// Create from bytes
212    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PqcError> {
213        if bytes.len() != ML_KEM_768_CIPHERTEXT_SIZE {
214            return Err(PqcError::InvalidCiphertextSize {
215                expected: ML_KEM_768_CIPHERTEXT_SIZE,
216                actual: bytes.len(),
217            });
218        }
219        let mut ct = Box::new([0u8; ML_KEM_768_CIPHERTEXT_SIZE]);
220        ct.copy_from_slice(bytes);
221        Ok(Self(ct))
222    }
223}
224
225impl Serialize for MlKemCiphertext {
226    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
227    where
228        S: serde::Serializer,
229    {
230        serializer.serialize_bytes(self.as_bytes())
231    }
232}
233
234impl<'de> Deserialize<'de> for MlKemCiphertext {
235    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
236    where
237        D: serde::Deserializer<'de>,
238    {
239        let bytes = <Vec<u8>>::deserialize(deserializer)?;
240        Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
241    }
242}
243
244/// ML-DSA-65 public key
245#[derive(Clone)]
246pub struct MlDsaPublicKey(pub Box<[u8; ML_DSA_65_PUBLIC_KEY_SIZE]>);
247
248impl std::fmt::Debug for MlDsaPublicKey {
249    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250        write!(f, "MlDsaPublicKey({} bytes)", self.0.len())
251    }
252}
253
254impl MlDsaPublicKey {
255    /// Get the public key as bytes
256    pub fn as_bytes(&self) -> &[u8] {
257        &self.0[..]
258    }
259
260    /// Create from bytes
261    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PqcError> {
262        if bytes.len() != ML_DSA_65_PUBLIC_KEY_SIZE {
263            return Err(PqcError::InvalidKeySize {
264                expected: ML_DSA_65_PUBLIC_KEY_SIZE,
265                actual: bytes.len(),
266            });
267        }
268        let mut key = Box::new([0u8; ML_DSA_65_PUBLIC_KEY_SIZE]);
269        key.copy_from_slice(bytes);
270        Ok(Self(key))
271    }
272}
273
274impl Serialize for MlDsaPublicKey {
275    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
276    where
277        S: serde::Serializer,
278    {
279        serializer.serialize_bytes(self.as_bytes())
280    }
281}
282
283impl<'de> Deserialize<'de> for MlDsaPublicKey {
284    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
285    where
286        D: serde::Deserializer<'de>,
287    {
288        let bytes = <Vec<u8>>::deserialize(deserializer)?;
289        Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
290    }
291}
292
293/// ML-DSA-65 secret key
294#[derive(ZeroizeOnDrop)]
295pub struct MlDsaSecretKey(pub Box<[u8; ML_DSA_65_SECRET_KEY_SIZE]>);
296
297impl Zeroize for MlDsaSecretKey {
298    fn zeroize(&mut self) {
299        self.0.as_mut().zeroize();
300    }
301}
302
303impl Clone for MlDsaSecretKey {
304    fn clone(&self) -> Self {
305        let mut key = Box::new([0u8; ML_DSA_65_SECRET_KEY_SIZE]);
306        key.copy_from_slice(&self.0[..]);
307        Self(key)
308    }
309}
310
311impl std::fmt::Debug for MlDsaSecretKey {
312    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
313        // Redact secret key content for security
314        f.debug_struct("MlDsaSecretKey")
315            .field("len", &ML_DSA_65_SECRET_KEY_SIZE)
316            .finish_non_exhaustive()
317    }
318}
319
320impl MlDsaSecretKey {
321    /// Get the secret key as bytes
322    pub fn as_bytes(&self) -> &[u8] {
323        &self.0[..]
324    }
325
326    /// Create from bytes
327    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PqcError> {
328        if bytes.len() != ML_DSA_65_SECRET_KEY_SIZE {
329            return Err(PqcError::InvalidKeySize {
330                expected: ML_DSA_65_SECRET_KEY_SIZE,
331                actual: bytes.len(),
332            });
333        }
334        let mut key = Box::new([0u8; ML_DSA_65_SECRET_KEY_SIZE]);
335        key.copy_from_slice(bytes);
336        Ok(Self(key))
337    }
338}
339
340impl Serialize for MlDsaSecretKey {
341    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
342    where
343        S: serde::Serializer,
344    {
345        serializer.serialize_bytes(self.as_bytes())
346    }
347}
348
349impl<'de> Deserialize<'de> for MlDsaSecretKey {
350    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
351    where
352        D: serde::Deserializer<'de>,
353    {
354        let bytes = <Vec<u8>>::deserialize(deserializer)?;
355        Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
356    }
357}
358
359/// ML-DSA-65 signature
360#[derive(Clone)]
361pub struct MlDsaSignature(pub Box<[u8; ML_DSA_65_SIGNATURE_SIZE]>);
362
363impl MlDsaSignature {
364    /// Get the signature as bytes
365    pub fn as_bytes(&self) -> &[u8] {
366        &self.0[..]
367    }
368
369    /// Create from bytes
370    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PqcError> {
371        if bytes.len() != ML_DSA_65_SIGNATURE_SIZE {
372            return Err(PqcError::InvalidSignatureSize {
373                expected: ML_DSA_65_SIGNATURE_SIZE,
374                actual: bytes.len(),
375            });
376        }
377        let mut sig = Box::new([0u8; ML_DSA_65_SIGNATURE_SIZE]);
378        sig.copy_from_slice(bytes);
379        Ok(Self(sig))
380    }
381}
382
383impl Serialize for MlDsaSignature {
384    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
385    where
386        S: serde::Serializer,
387    {
388        serializer.serialize_bytes(self.as_bytes())
389    }
390}
391
392impl<'de> Deserialize<'de> for MlDsaSignature {
393    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
394    where
395        D: serde::Deserializer<'de>,
396    {
397        let bytes = <Vec<u8>>::deserialize(deserializer)?;
398        Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
399    }
400}
401
402/// Shared secret from key encapsulation
403#[derive(Clone, Zeroize, ZeroizeOnDrop)]
404pub struct SharedSecret(pub [u8; ML_KEM_768_SHARED_SECRET_SIZE]);
405
406impl std::fmt::Debug for SharedSecret {
407    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
408        write!(f, "SharedSecret([..{}])", self.0.len())
409    }
410}
411
412impl SharedSecret {
413    /// Get the shared secret as a byte slice
414    pub fn as_bytes(&self) -> &[u8] {
415        &self.0
416    }
417
418    /// Create from bytes
419    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PqcError> {
420        if bytes.len() != ML_KEM_768_SHARED_SECRET_SIZE {
421            return Err(PqcError::InvalidKeySize {
422                expected: ML_KEM_768_SHARED_SECRET_SIZE,
423                actual: bytes.len(),
424            });
425        }
426        let mut secret = [0u8; ML_KEM_768_SHARED_SECRET_SIZE];
427        secret.copy_from_slice(bytes);
428        Ok(Self(secret))
429    }
430}
431
432// v0.2: Hybrid types removed - pure PQC only
433// This is a greenfield network with no legacy compatibility requirements.
434
435#[cfg(test)]
436mod tests {
437    use super::*;
438
439    #[test]
440    fn test_pqc_error_conversions() {
441        // Test error type conversions and display
442        let err = PqcError::InvalidKeySize {
443            expected: 1184,
444            actual: 1000,
445        };
446        assert_eq!(err.to_string(), "Invalid key size: expected 1184, got 1000");
447
448        let err = PqcError::KeyGenerationFailed("test failure".to_string());
449        assert_eq!(err.to_string(), "Key generation failed: test failure");
450    }
451
452    #[test]
453    fn test_constant_sizes() {
454        // Verify constant sizes match NIST standards
455        assert_eq!(ML_KEM_768_PUBLIC_KEY_SIZE, 1184);
456        assert_eq!(ML_KEM_768_SECRET_KEY_SIZE, 2400);
457        assert_eq!(ML_KEM_768_CIPHERTEXT_SIZE, 1088);
458        assert_eq!(ML_KEM_768_SHARED_SECRET_SIZE, 32);
459
460        assert_eq!(ML_DSA_65_PUBLIC_KEY_SIZE, 1952);
461        assert_eq!(ML_DSA_65_SECRET_KEY_SIZE, 4032);
462        assert_eq!(ML_DSA_65_SIGNATURE_SIZE, 3309);
463    }
464
465    #[test]
466    fn test_ml_kem_public_key_serialization() {
467        // Create a test public key
468        let test_data = vec![42u8; ML_KEM_768_PUBLIC_KEY_SIZE];
469        let key = MlKemPublicKey::from_bytes(&test_data).unwrap();
470
471        // Serialize
472        let serialized = serde_json::to_string(&key).unwrap();
473
474        // Deserialize
475        let deserialized: MlKemPublicKey = serde_json::from_str(&serialized).unwrap();
476
477        // Verify
478        assert_eq!(key.as_bytes(), deserialized.as_bytes());
479    }
480
481    #[test]
482    fn test_ml_kem_secret_key_serialization() {
483        // Create a test secret key
484        let test_data = vec![43u8; ML_KEM_768_SECRET_KEY_SIZE];
485        let key = MlKemSecretKey::from_bytes(&test_data).unwrap();
486
487        // Serialize
488        let serialized = serde_json::to_string(&key).unwrap();
489
490        // Deserialize
491        let deserialized: MlKemSecretKey = serde_json::from_str(&serialized).unwrap();
492
493        // Verify
494        assert_eq!(key.as_bytes(), deserialized.as_bytes());
495    }
496
497    #[test]
498    fn test_ml_kem_ciphertext_serialization() {
499        // Create a test ciphertext
500        let test_data = vec![44u8; ML_KEM_768_CIPHERTEXT_SIZE];
501        let ct = MlKemCiphertext::from_bytes(&test_data).unwrap();
502
503        // Serialize
504        let serialized = serde_json::to_string(&ct).unwrap();
505
506        // Deserialize
507        let deserialized: MlKemCiphertext = serde_json::from_str(&serialized).unwrap();
508
509        // Verify
510        assert_eq!(ct.as_bytes(), deserialized.as_bytes());
511    }
512
513    #[test]
514    fn test_ml_dsa_public_key_serialization() {
515        // Create a test public key
516        let test_data = vec![45u8; ML_DSA_65_PUBLIC_KEY_SIZE];
517        let key = MlDsaPublicKey::from_bytes(&test_data).unwrap();
518
519        // Serialize
520        let serialized = serde_json::to_string(&key).unwrap();
521
522        // Deserialize
523        let deserialized: MlDsaPublicKey = serde_json::from_str(&serialized).unwrap();
524
525        // Verify
526        assert_eq!(key.as_bytes(), deserialized.as_bytes());
527    }
528
529    #[test]
530    fn test_ml_dsa_secret_key_serialization() {
531        // Create a test secret key
532        let test_data = vec![46u8; ML_DSA_65_SECRET_KEY_SIZE];
533        let key = MlDsaSecretKey::from_bytes(&test_data).unwrap();
534
535        // Serialize
536        let serialized = serde_json::to_string(&key).unwrap();
537
538        // Deserialize
539        let deserialized: MlDsaSecretKey = serde_json::from_str(&serialized).unwrap();
540
541        // Verify
542        assert_eq!(key.as_bytes(), deserialized.as_bytes());
543    }
544
545    #[test]
546    fn test_ml_dsa_signature_serialization() {
547        // Create a test signature
548        let test_data = vec![47u8; ML_DSA_65_SIGNATURE_SIZE];
549        let sig = MlDsaSignature::from_bytes(&test_data).unwrap();
550
551        // Serialize
552        let serialized = serde_json::to_string(&sig).unwrap();
553
554        // Deserialize
555        let deserialized: MlDsaSignature = serde_json::from_str(&serialized).unwrap();
556
557        // Verify
558        assert_eq!(sig.as_bytes(), deserialized.as_bytes());
559    }
560}