Skip to main content

dcrypt_algorithms/ec/
mod.rs

1// File: crates/algorithms/src/ec/mod.rs
2//! Elliptic Curve Primitives
3//!
4//! This module provides low-level elliptic-curve operations on several curves.
5//! Individual implementations use timing-aware techniques, but the module has
6//! no blanket compiler- or target-level constant-time guarantee and is not by
7//! itself a complete protocol such as RFC 9180 HPKE.
8//! The prime curves retained for v3 are P-224, P-256, P-384, P-521, and
9//! secp256k1. P-192 and sect283k1 were removed: P-192 is legacy-only in
10//! NIST SP 800-186, while the previous sect283k1 implementation used an
11//! incorrect group order and did not validate subgroup membership.
12
13pub mod bls12_381;
14pub mod k256;
15pub mod p224;
16pub mod p256;
17pub mod p384;
18pub mod p521;
19
20// Re-export types with consistent naming scheme.
21// This corrects the original error which tried to export non-existent types like 'PointG1'.
22pub use bls12_381::{
23    pairing as bls12_381_pairing, Bls12_381Scalar, G1Projective as Bls12_381G1,
24    G2Projective as Bls12_381G2, Gt as Bls12_381Gt,
25};
26
27pub use k256::{Point as K256Point, Scalar as K256Scalar};
28pub use p224::{Point as P224Point, Scalar as P224Scalar};
29pub use p256::{Point as P256Point, Scalar as P256Scalar};
30pub use p384::{Point as P384Point, Scalar as P384Scalar};
31pub use p521::{Point as P521Point, Scalar as P521Scalar};
32
33/// Common trait for coordinate systems used in elliptic curve operations
34pub trait CoordinateSystem {}
35
36/// Affine coordinates (x,y)
37pub struct Affine;
38impl CoordinateSystem for Affine {}
39
40/// Jacobian projective coordinates (X:Y:Z) where x = X/Z² and y = Y/Z³
41pub struct Jacobian;
42impl CoordinateSystem for Jacobian {}
43
44#[cfg(test)]
45mod scalar_storage_policy_tests {
46    const SCALAR_SOURCES: [(&str, &str); 5] = [
47        ("p224", include_str!("p224/scalar.rs")),
48        ("p256", include_str!("p256/scalar.rs")),
49        ("p384", include_str!("p384/scalar.rs")),
50        ("p521", include_str!("p521/scalar.rs")),
51        ("k256", include_str!("k256/scalar.rs")),
52    ];
53
54    #[test]
55    fn retained_scalar_sources_keep_secret_storage_raii_protected() {
56        for (curve, source) in SCALAR_SOURCES {
57            assert!(
58                source.contains("Self::from_secret_buffer(SecretBuffer::new(data))"),
59                "{curve} must protect raw constructor input before validation"
60            );
61            assert!(
62                source.contains("let mut protected = SecretBuffer::zeroed();")
63                    && source.contains("protected.as_mut().copy_from_slice(bytes);"),
64                "{curve} deserialization must copy directly into protected storage"
65            );
66            assert!(
67                source.contains("pub fn serialize(&self) -> SecretBuffer<"),
68                "{curve} serialization must return protected exact-size storage"
69            );
70
71            for forbidden in [
72                "-> [u8;",
73                "-> [u32;",
74                ".to_be_bytes()",
75                ".to_le_bytes()",
76                "from_be_bytes([",
77                "from_le_bytes([",
78                "let original = *bytes",
79                "bytes[i] = u8::conditional_select",
80            ] {
81                assert!(
82                    !source.contains(forbidden),
83                    "{curve} scalar source contains forbidden unprotected storage pattern: {forbidden}"
84                );
85            }
86
87            for line in source.lines() {
88                let line = line.trim_start();
89                let raw_local_array = line.starts_with("let ")
90                    && (line.contains(" = [")
91                        || line.contains(": [u8;")
92                        || line.contains(": [u32;"));
93                assert!(
94                    !raw_local_array,
95                    "{curve} scalar source declares an unprotected local array: {line}"
96                );
97            }
98        }
99
100        for (curve, source) in SCALAR_SOURCES.into_iter().take(4) {
101            assert!(
102                source.contains("let mut protected = SecretBuffer::new(data);"),
103                "{curve} reduction must protect raw input before arithmetic"
104            );
105            assert!(
106                source.contains("Zeroizing::new([0u32;"),
107                "{curve} limb scratch must use zeroize-on-drop storage"
108            );
109            assert!(
110                source.contains("#[inline(never)]\n    fn select_secret_buffer("),
111                "{curve} selection must retain its compiler-reviewed mask boundary"
112            );
113        }
114    }
115}