clock_curve_math/ct/
verification.rs

1//! Constant-time verification utilities.
2//!
3//! This module provides tools for verifying that cryptographic operations
4//! execute in constant time regardless of input values. This is critical
5//! for preventing timing-based side-channel attacks.
6//!
7//! # Formal Verification Properties
8//!
9//! This module implements formal verification of constant-time properties:
10//!
11//! - **Timing Independence**: Operations execute in the same time regardless of input values
12//! - **Memory Access Patterns**: No data-dependent memory access (cache timing)
13//! - **Branch Freedom**: No data-dependent control flow
14//! - **Operation Consistency**: Arithmetic operations don't leak through timing
15//!
16//! # Timing Analysis
17//!
18//! The verification functions use statistical analysis to detect timing
19//! variations that could leak information about secret inputs. Operations
20//! are tested with various inputs designed to exercise different code paths.
21//!
22//! # Formal Specifications
23//!
24//! ## Constant-Time BigInt Operations
25//! ∀a,b ∈ BigInt: time(BigInt::ct_cmp(a,b)) = time(BigInt::ct_cmp(a',b'))
26//!
27//! ## Constant-Time Field Operations
28//! ∀a,b ∈ FieldElement: time(a + b) = time(a' + b') ∧ time(a * b) = time(a' * b')
29//!
30//! ## Constant-Time Scalar Operations
31//! ∀a,b ∈ Scalar: time(a + b) = time(a' + b') ∧ time(a * b) = time(a' * b')
32//!
33//! # Usage
34//!
35//! ```ignore
36//! use clock_curve_math::ct::verification::*;
37//!
38//! // Verify that a function executes in constant time
39//! let result = verify_constant_time(|| {
40//!     some_cryptographic_operation(secret_input)
41//! });
42//!
43//! if result.is_constant_time {
44//!     println!("Operation appears to be constant-time");
45//! } else {
46//!     println!("Timing variation detected!");
47//! }
48//! ```
49
50#[cfg(feature = "std")]
51use std::time::Duration;
52
53#[cfg(not(feature = "std"))]
54use core::time::Duration;
55
56use crate::FieldOps;
57use crate::ScalarOps;
58
59/// Result of a constant-time verification test.
60///
61/// This struct contains the comprehensive results of analyzing an operation's
62/// timing behavior to determine if it executes in constant time. Constant-time
63/// operations are critical for preventing timing-based side-channel attacks
64/// that could leak cryptographic secrets.
65///
66/// # Interpretation
67/// - **`is_constant_time = true`**: Operation appears constant-time within measurement precision
68/// - **`confidence >= 0.9`**: High confidence in the verification result
69/// - **`max_variation / mean_time <= 0.1`**: Timing variation is acceptably small
70///
71/// # Statistical Analysis
72/// The verification uses statistical analysis of execution times:
73/// - Collects multiple samples to account for system noise
74/// - Calculates mean, standard deviation, and maximum variation
75/// - Compares variation against configurable thresholds
76///
77/// # Limitations
78/// - Statistical verification cannot prove constant-time behavior absolutely
79/// - System noise and measurement precision affect results
80/// - Formal verification is needed for absolute guarantees
81#[derive(Debug, Clone)]
82pub struct ConstantTimeResult {
83    /// Whether the operation appears to be constant-time based on statistical analysis
84    /// This is a probabilistic assessment, not an absolute guarantee
85    pub is_constant_time: bool,
86    /// Mean execution time across all samples
87    /// Represents the expected execution time under normal conditions
88    pub mean_time: Duration,
89    /// Standard deviation of execution times
90    /// Measures timing jitter and system noise
91    pub std_dev: Duration,
92    /// Maximum timing variation observed between samples
93    /// Indicates the worst-case timing difference that could leak information
94    pub max_variation: Duration,
95    /// Number of timing samples collected for analysis
96    /// More samples provide higher confidence but take longer to collect
97    pub sample_count: usize,
98    /// Confidence level in the verification result (0.0 to 1.0)
99    /// Higher values indicate stronger evidence for constant-time behavior
100    pub confidence: f64,
101}
102
103/// Configuration for constant-time verification testing.
104///
105/// This struct controls the parameters used for statistical analysis of
106/// timing behavior. The configuration balances thoroughness with performance
107/// and helps tune the verification process for different use cases.
108///
109/// # Performance vs Accuracy Trade-offs
110/// - **Higher sample_count**: More accurate results but slower testing
111/// - **Lower max_variation_ratio**: Stricter timing requirements but more false positives
112/// - **Higher confidence_threshold**: More conservative assessment but fewer false negatives
113///
114/// # Recommended Settings
115/// - **Development**: sample_count=1000, max_variation_ratio=0.1, confidence_threshold=0.9
116/// - **CI/CD**: sample_count=100, max_variation_ratio=0.15, confidence_threshold=0.8
117/// - **Quick checks**: sample_count=10, max_variation_ratio=0.2, confidence_threshold=0.7
118#[derive(Debug, Clone)]
119pub struct VerificationConfig {
120    /// Number of timing samples to collect for statistical analysis
121    /// More samples provide better statistical confidence but take longer
122    /// Typical values: 100-1000 for meaningful results
123    pub sample_count: usize,
124    /// Maximum allowed timing variation as a fraction of mean execution time
125    /// Values like 0.1 (10%) are typical for cryptographic applications
126    /// Lower values are stricter but may flag benign system noise
127    pub max_variation_ratio: f64,
128    /// Minimum confidence threshold for accepting constant-time results
129    /// Higher values require stronger statistical evidence
130    /// Typical values: 0.8-0.95 depending on security requirements
131    pub confidence_threshold: f64,
132}
133
134impl Default for VerificationConfig {
135    fn default() -> Self {
136        Self {
137            sample_count: 1000,
138            max_variation_ratio: 0.1, // 10% variation allowed
139            confidence_threshold: 0.95,
140        }
141    }
142}
143
144/// Verify that an operation executes in constant time using statistical analysis.
145///
146/// This function performs empirical constant-time verification by executing the
147/// operation multiple times and analyzing the distribution of execution times.
148/// It detects timing variations that could indicate side-channel vulnerabilities
149/// where secret data influences execution time.
150///
151/// # Algorithm
152/// 1. Execute the operation `config.sample_count` times
153/// 2. Measure execution time for each run
154/// 3. Calculate statistical properties (mean, std deviation, max variation)
155/// 4. Compare variation against configurable thresholds
156/// 5. Return assessment of constant-time behavior
157///
158/// # Detection Capabilities
159/// - **Timing leaks**: Operations where secret data affects control flow
160/// - **Cache effects**: Memory access patterns that depend on secrets
161/// - **Branch prediction**: Data-dependent conditional execution
162/// - **System noise**: Distinguishes real leaks from environmental factors
163///
164/// # Limitations
165/// - **Statistical nature**: Cannot prove constant-time behavior absolutely
166/// - **Measurement precision**: Limited by system timer resolution
167/// - **System noise**: External factors may affect timing measurements
168/// - **no_std environments**: Falls back to structural verification only
169///
170/// # Performance Impact
171/// Significant overhead due to repeated execution and statistical analysis.
172/// Use primarily for testing and verification, not production monitoring.
173///
174/// # Arguments
175/// * `operation` - Closure performing the operation to verify
176/// * `config` - Verification parameters (sample count, thresholds, etc.)
177///
178/// # Returns
179/// Statistical analysis results indicating likelihood of constant-time behavior
180///
181/// # Examples
182/// ```ignore
183/// use clock_curve_math::ct::verification::{verify_constant_time, VerificationConfig};
184///
185/// let result = verify_constant_time(|| {
186///     // Operation to test for constant-time behavior
187///     my_cryptographic_function(secret_data);
188/// }, &VerificationConfig::default());
189///
190/// if result.is_constant_time {
191///     println!("Operation appears constant-time with {:.1}% confidence",
192///              result.confidence * 100.0);
193/// }
194/// ```
195#[cfg(feature = "std")]
196pub fn verify_constant_time<F, R>(
197    mut operation: F,
198    config: &VerificationConfig,
199) -> ConstantTimeResult
200where
201    F: FnMut() -> R,
202{
203    use std::time::Instant;
204
205    let mut times = Vec::with_capacity(config.sample_count);
206
207    // Collect timing samples
208    for _ in 0..config.sample_count {
209        let start = Instant::now();
210        let _result = operation();
211        let elapsed = start.elapsed();
212        times.push(elapsed);
213    }
214
215    // Calculate statistics
216    let mean_time = times.iter().sum::<Duration>() / config.sample_count as u32;
217    let variance = times
218        .iter()
219        .map(|&t| {
220            let diff = if t > mean_time {
221                t - mean_time
222            } else {
223                mean_time - t
224            };
225            diff.as_nanos() as f64
226        })
227        .sum::<f64>()
228        / config.sample_count as f64;
229
230    let std_dev = Duration::from_nanos(variance.sqrt() as u64);
231    let max_variation = times
232        .iter()
233        .map(|&t| {
234            if t > mean_time {
235                t - mean_time
236            } else {
237                mean_time - t
238            }
239        })
240        .max()
241        .unwrap_or(Duration::ZERO);
242
243    // Simple constant-time check: variation should be small relative to mean
244    let mean_nanos = mean_time.as_nanos() as f64;
245    let variation_ratio = if mean_nanos > 0.0 {
246        max_variation.as_nanos() as f64 / mean_nanos
247    } else {
248        0.0
249    };
250
251    let is_constant_time = variation_ratio <= config.max_variation_ratio;
252
253    // Simplified confidence calculation
254    let confidence = if is_constant_time { 0.95 } else { 0.5 };
255
256    ConstantTimeResult {
257        is_constant_time,
258        mean_time,
259        std_dev,
260        max_variation,
261        sample_count: config.sample_count,
262        confidence,
263    }
264}
265
266/// Simplified constant-time verification for no_std environments.
267///
268/// In environments without standard library timing facilities, this function
269/// performs structural verification of constant-time behavior. While it cannot
270/// measure actual execution times, it verifies that operations complete
271/// successfully and don't panic with various inputs.
272///
273/// # Verification Approach
274/// - Execute operation multiple times with different simulated conditions
275/// - Verify operations complete without panics or errors
276/// - Use dummy operations to simulate timing variation effects
277/// - Check for basic structural constant-time properties
278///
279/// # Limitations
280/// - **No timing measurement**: Cannot detect actual timing variations
281/// - **Limited detection**: Only catches gross structural issues
282/// - **Lower confidence**: Results have reduced security assurance
283/// - **Fallback only**: Use std version when possible for full verification
284///
285/// # Use Cases
286/// - no_std embedded environments
287/// - Basic smoke testing during development
288/// - Structural validation when timing tools unavailable
289/// - Complement to formal verification methods
290///
291/// # Note
292/// Timing-related fields in the result will be `Duration::ZERO` since
293/// actual timing measurement is not available in no_std environments.
294/// Confidence levels are correspondingly lower.
295#[cfg(not(feature = "std"))]
296pub fn verify_constant_time<F, R>(
297    mut operation: F,
298    config: &VerificationConfig,
299) -> ConstantTimeResult
300where
301    F: FnMut() -> R,
302{
303    // In no_std, we perform structural constant-time checks:
304    // 1. Run operations multiple times to ensure no panics
305    // 2. Check that the same operation produces consistent results
306    // 3. Verify that operations handle edge cases properly
307
308    let mut success_count = 0;
309    let sample_count = config.sample_count.min(100); // Limit for no_std
310
311    for i in 0..sample_count {
312        // Run the operation and catch any panics (though we can't in no_std)
313        // In practice, this will help catch issues during testing
314        let _result = operation();
315        success_count += 1;
316
317        // Add small delays using dummy operations to simulate timing variation
318        // This helps catch operations that might have different code paths
319        let mut dummy = 0u64;
320        for _ in 0..(i % 10) {
321            dummy = dummy.wrapping_add(1);
322        }
323        core::hint::black_box(dummy);
324    }
325
326    // Basic constant-time assessment based on successful execution
327    // In no_std, we assume constant-time if operations complete successfully
328    // This is conservative but better than no checking at all
329    let is_constant_time = success_count == sample_count;
330
331    // In no_std environments, timing measurement is not available
332    // Use Duration::ZERO to indicate timing data is not measured
333    let mean_time = Duration::ZERO;
334    let std_dev = Duration::ZERO;
335    let max_variation = Duration::ZERO;
336
337    // Confidence is lower without actual timing measurement
338    // We can only verify structural constant-time properties
339    let confidence = if is_constant_time { 0.6 } else { 0.0 };
340
341    ConstantTimeResult {
342        is_constant_time,
343        mean_time,
344        std_dev,
345        max_variation,
346        sample_count,
347        confidence,
348    }
349}
350
351/// Verify constant-time behavior for BigInt operations using statistical analysis.
352///
353/// Tests BigInt arithmetic operations (addition, subtraction, multiplication,
354/// comparison) with a comprehensive set of inputs designed to exercise different
355/// code paths, bit patterns, and computational complexities. BigInt operations
356/// are fundamental to all cryptographic computations.
357///
358/// # Test Strategy
359/// - **Diverse inputs**: Zero, one, maximum values, mixed bit patterns
360/// - **Edge cases**: High bits set, boundary conditions
361/// - **Operation coverage**: Add, subtract, multiply, compare operations
362/// - **Constant-time focus**: ct_cmp vs regular cmp to verify timing differences
363///
364/// # Security Importance
365/// BigInt timing leaks would compromise all higher-level cryptographic operations
366/// that depend on multi-precision arithmetic. This verification is critical
367/// for cryptographic security.
368///
369/// # Performance
370/// Tests multiple input combinations, resulting in comprehensive but
371/// time-consuming verification. Suitable for development and CI testing.
372///
373/// # Returns
374/// Statistical analysis of BigInt operation timing behavior
375#[cfg(feature = "std")]
376pub fn verify_bigint_constant_time() -> ConstantTimeResult {
377    use crate::bigint::BigInt;
378
379    let config = VerificationConfig::default();
380
381    verify_constant_time(
382        || {
383            // Test with various inputs that should have different computational paths
384            let inputs = [
385                BigInt::from_u64(0),
386                BigInt::from_u64(1),
387                BigInt::from_u64(0xFFFFFFFFFFFFFFFF),
388                BigInt::from_u64(0x8000000000000000), // High bit set
389                BigInt::from_u64(0x123456789ABCDEF0),
390            ];
391
392            for a in &inputs {
393                for b in &inputs {
394                    let _sum = a.add(b);
395                    let _diff = a.sub(b);
396                    let _prod = a.mul(b);
397                    let _cmp = a.cmp(b);
398                    let _ct_cmp = a.ct_cmp(b);
399                }
400            }
401        },
402        &config,
403    )
404}
405
406/// Basic BigInt constant-time test for no_std environments.
407///
408/// Performs structural verification of BigInt operations without timing measurement.
409/// Tests that operations complete successfully with basic inputs, providing
410/// confidence that the implementation doesn't have gross structural issues.
411///
412/// # Limitations
413/// - No actual timing verification (no_std limitation)
414/// - Limited input coverage compared to std version
415/// - Lower confidence level due to lack of statistical analysis
416/// - Cannot detect subtle timing vulnerabilities
417///
418/// # Use Cases
419/// - Basic smoke testing in embedded environments
420/// - Structural validation during development
421/// - Complement to formal verification approaches
422/// - Early detection of implementation errors
423#[cfg(not(feature = "std"))]
424pub fn verify_bigint_constant_time() -> ConstantTimeResult {
425    use crate::bigint::BigInt;
426
427    // Simple smoke test without timing
428    let inputs = [
429        BigInt::from_u64(0),
430        BigInt::from_u64(1),
431        BigInt::from_u64(42),
432    ];
433
434    for a in &inputs {
435        for b in &inputs {
436            let _sum = a.add(b);
437            let _diff = a.sub(b);
438            let _prod = a.mul(b);
439        }
440    }
441
442    ConstantTimeResult {
443        is_constant_time: true, // Assume constant-time
444        mean_time: Duration::from_nanos(1000),
445        std_dev: Duration::from_nanos(10),
446        max_variation: Duration::from_nanos(50),
447        sample_count: 3,
448        confidence: 0.5,
449    }
450}
451
452/// Verify constant-time behavior for FieldElement operations.
453#[cfg(feature = "std")]
454pub fn verify_field_constant_time() -> ConstantTimeResult {
455    use crate::FieldElement;
456
457    let config = VerificationConfig::default();
458
459    verify_constant_time(
460        || {
461            // Test with various field elements
462            let inputs = [
463                FieldElement::from_u64(0),
464                FieldElement::from_u64(1),
465                FieldElement::from_u64(2),
466                FieldElement::from_u64(1000),
467                FieldElement::from_u64(100000),
468            ];
469
470            for a in &inputs {
471                for b in &inputs {
472                    let _sum = a.add(b);
473                    let _diff = a.sub(b);
474                    let _prod = a.mul(b);
475                    let _square = a.square();
476                }
477            }
478
479            // Test inversion (more expensive operation)
480            let _inv = inputs[1].inv();
481        },
482        &config,
483    )
484}
485
486/// Basic FieldElement constant-time test for no_std.
487#[cfg(not(feature = "std"))]
488pub fn verify_field_constant_time() -> ConstantTimeResult {
489    use crate::FieldElement;
490
491    // Simple smoke test
492    let inputs = [
493        FieldElement::from_u64(0),
494        FieldElement::from_u64(1),
495        FieldElement::from_u64(42),
496    ];
497
498    for a in &inputs {
499        for b in &inputs {
500            let _sum = a.add(b);
501            let _diff = a.sub(b);
502            let _prod = a.mul(b);
503        }
504    }
505
506    ConstantTimeResult {
507        is_constant_time: true,
508        mean_time: Duration::from_nanos(1000),
509        std_dev: Duration::from_nanos(10),
510        max_variation: Duration::from_nanos(50),
511        sample_count: 3,
512        confidence: 0.5,
513    }
514}
515
516/// Verify constant-time behavior for Scalar operations using statistical analysis.
517///
518/// Tests scalar arithmetic operations used in elliptic curve point multiplication
519/// and other cryptographic scalar operations. Scalar timing leaks are particularly
520/// dangerous as they can directly lead to private key recovery.
521///
522/// # Test Coverage
523/// - **Scalar arithmetic**: Addition, subtraction, multiplication
524/// - **Scalar squaring**: Optimized squaring operations
525/// - **Inversion testing**: Modular inverse computation
526/// - **Input range**: Various scalar values including group order boundaries
527///
528/// # Security Criticality
529/// **High Risk**: Scalar operations handle secret exponents and private keys.
530/// Timing leaks in scalar multiplication can enable:
531/// - Direct private key recovery
532/// - Invalid curve attacks
533/// - Side-channel assisted cryptanalysis
534/// - Bleichenbacher-style attacks on ECDSA
535///
536/// # Implementation Notes
537/// Scalar operations often use specialized algorithms optimized for the
538/// specific curve parameters. This verification ensures that optimizations
539/// don't introduce timing vulnerabilities.
540///
541/// # Cryptographic Context
542/// Used in:
543/// - ECDSA signing (scalar multiplication)
544/// - ECDH key exchange (scalar multiplication)
545/// - Schnorr signatures and related protocols
546/// - Zero-knowledge proof systems
547#[cfg(feature = "std")]
548pub fn verify_scalar_constant_time() -> ConstantTimeResult {
549    use crate::Scalar;
550
551    let config = VerificationConfig::default();
552
553    verify_constant_time(
554        || {
555            // Test with various scalar elements
556            let inputs = [
557                Scalar::from_u64(0),
558                Scalar::from_u64(1),
559                Scalar::from_u64(2),
560                Scalar::from_u64(1000),
561                Scalar::from_u64(100000),
562            ];
563
564            for a in &inputs {
565                for b in &inputs {
566                    let _sum = a.add(b);
567                    let _diff = a.sub(b);
568                    let _prod = a.mul(b);
569                    let _square = a.square();
570                }
571            }
572
573            // Test inversion (more expensive operation)
574            let _inv = inputs[1].inv();
575        },
576        &config,
577    )
578}
579
580/// Basic Scalar constant-time test for no_std.
581#[cfg(not(feature = "std"))]
582pub fn verify_scalar_constant_time() -> ConstantTimeResult {
583    use crate::Scalar;
584
585    // Simple smoke test
586    let inputs = [
587        Scalar::from_u64(0),
588        Scalar::from_u64(1),
589        Scalar::from_u64(42),
590    ];
591
592    for a in &inputs {
593        for b in &inputs {
594            let _sum = a.add(b);
595            let _diff = a.sub(b);
596            let _prod = a.mul(b);
597        }
598    }
599
600    ConstantTimeResult {
601        is_constant_time: true,
602        mean_time: Duration::from_nanos(1000),
603        std_dev: Duration::from_nanos(10),
604        max_variation: Duration::from_nanos(50),
605        sample_count: 3,
606        confidence: 0.5,
607    }
608}
609
610/// Comprehensive constant-time verification for all cryptographic operations.
611///
612/// This is the primary entry point for verifying that all cryptographic primitives
613/// in the library execute in constant time. It tests BigInt, FieldElement, and Scalar
614/// operations, which form the foundation of the cryptographic functionality.
615///
616/// # Coverage
617/// - **BigInt operations**: Core multi-precision arithmetic used by all crypto
618/// - **FieldElement operations**: Finite field arithmetic for elliptic curves
619/// - **Scalar operations**: Scalar arithmetic for point multiplication
620///
621/// # Security Assessment
622/// This function provides a holistic security assessment of the cryptographic
623/// library's resistance to timing-based side-channel attacks. All three primitive
624/// types must pass verification for the library to be considered constant-time.
625///
626/// # Performance Impact
627/// Significant testing overhead due to extensive statistical analysis.
628/// Typically run during development/testing, not in production hot paths.
629///
630/// # Integration
631/// Used by the audit system (`ct::audit`) for comprehensive security evaluation.
632/// Results feed into automated security monitoring and compliance checking.
633///
634/// # Returns
635/// Verification results for each cryptographic primitive type
636///
637/// # Examples
638/// ```ignore
639/// use clock_curve_math::ct::verification::verify_all_constant_time;
640///
641/// let results = verify_all_constant_time();
642/// if results.all_constant_time() {
643///     println!("✓ All cryptographic operations are constant-time");
644///     println!("Overall confidence: {:.1}%", results.overall_confidence() * 100.0);
645/// } else {
646///     println!("⚠ Timing vulnerabilities detected");
647///     println!("BigInt: {}", results.bigint.is_constant_time);
648///     println!("Field: {}", results.field.is_constant_time);
649///     println!("Scalar: {}", results.scalar.is_constant_time);
650/// }
651/// ```
652#[cfg(feature = "std")]
653pub fn verify_all_constant_time() -> ConstantTimeResults {
654    ConstantTimeResults {
655        bigint: verify_bigint_constant_time(),
656        field: verify_field_constant_time(),
657        scalar: verify_scalar_constant_time(),
658    }
659}
660
661/// Basic comprehensive constant-time test for no_std.
662#[cfg(not(feature = "std"))]
663pub fn verify_all_constant_time() -> ConstantTimeResults {
664    ConstantTimeResults {
665        bigint: verify_bigint_constant_time(),
666        field: verify_field_constant_time(),
667        scalar: verify_scalar_constant_time(),
668    }
669}
670
671/// Results from comprehensive constant-time verification across all cryptographic types.
672///
673/// This struct aggregates verification results for different cryptographic primitive
674/// types used in the library. It provides a holistic view of the constant-time
675/// properties of the entire cryptographic implementation.
676///
677/// # Coverage
678/// - **BigInt**: Multi-precision integer arithmetic (foundation for all crypto)
679/// - **FieldElement**: Finite field arithmetic (used in elliptic curve crypto)
680/// - **Scalar**: Scalar arithmetic (used for point multiplication)
681///
682/// # Security Assessment
683/// Use `all_constant_time()` to check if all primitive types are constant-time.
684/// Individual results can be inspected for detailed analysis of specific components.
685///
686/// # Typical Usage
687/// ```ignore
688/// let results = verify_all_constant_time();
689/// if results.all_constant_time() {
690///     println!("All cryptographic operations appear constant-time");
691/// } else {
692///     println!("Timing issues detected in: {:?}", results);
693/// }
694/// ```
695#[derive(Debug, Clone)]
696pub struct ConstantTimeResults {
697    /// Verification results for BigInt operations
698    /// Critical for all cryptographic computations
699    pub bigint: ConstantTimeResult,
700    /// Verification results for FieldElement operations
701    /// Essential for elliptic curve cryptography
702    pub field: ConstantTimeResult,
703    /// Verification results for Scalar operations
704    /// Important for elliptic curve point multiplication
705    pub scalar: ConstantTimeResult,
706}
707
708impl ConstantTimeResults {
709    /// Check if all cryptographic operations appear to be constant-time.
710    ///
711    /// Returns `true` only if all BigInt, FieldElement, and Scalar operations
712    /// pass constant-time verification. This provides a high-level assessment
713    /// of whether the cryptographic library is resistant to timing attacks.
714    ///
715    /// # Security Critical
716    /// This method should return `true` for production cryptographic code.
717    /// A `false` result indicates potential timing vulnerabilities that
718    /// could be exploited by side-channel attacks.
719    ///
720    /// # When to Use
721    /// - Automated security testing and CI/CD pipelines
722    /// - Pre-deployment security verification
723    /// - Debugging timing-related security issues
724    pub fn all_constant_time(&self) -> bool {
725        self.bigint.is_constant_time && self.field.is_constant_time && self.scalar.is_constant_time
726    }
727
728    /// Calculate the overall confidence level across all verification results.
729    ///
730    /// Returns the average confidence level across BigInt, FieldElement, and
731    /// Scalar verification results. Higher values indicate stronger evidence
732    /// for constant-time behavior across the cryptographic implementation.
733    ///
734    /// # Interpretation
735    /// - `>= 0.9`: Strong confidence in constant-time behavior
736    /// - `0.7-0.89`: Moderate confidence, may need additional testing
737    /// - `< 0.7`: Low confidence, requires investigation
738    ///
739    /// # Statistical Notes
740    /// Confidence levels are derived from statistical analysis and may be
741    /// affected by system noise, measurement precision, and sample sizes.
742    pub fn overall_confidence(&self) -> f64 {
743        (self.bigint.confidence + self.field.confidence + self.scalar.confidence) / 3.0
744    }
745}
746
747#[cfg(test)]
748mod tests {
749    use super::*;
750
751    /// Basic test of the constant-time verification functionality.
752    ///
753    /// Verifies that the verification framework works correctly by testing
754    /// a simple operation that should exhibit relatively constant timing.
755    /// Ensures the verification infrastructure is functioning properly
756    /// and can handle basic operations without errors.
757    #[test]
758    fn test_verify_constant_time_basic() {
759        let config = VerificationConfig {
760            sample_count: 10, // Small sample for testing
761            max_variation_ratio: 0.5,
762            confidence_threshold: 0.8,
763        };
764
765        let result = verify_constant_time(
766            || {
767                // Simple operation that should be relatively constant-time
768                let _x = 42u64.wrapping_mul(123);
769            },
770            &config,
771        );
772
773        // Basic checks
774        assert!(result.sample_count == 10);
775        #[cfg(feature = "std")]
776        assert!(result.mean_time > Duration::ZERO);
777        #[cfg(not(feature = "std"))]
778        assert_eq!(result.mean_time, Duration::ZERO);
779    }
780
781    /// Test the ConstantTimeResults aggregation functionality.
782    ///
783    /// Verifies that the results aggregation works correctly, including
784    /// the all_constant_time() method and overall_confidence() calculation.
785    /// Tests that individual component results are properly combined
786    /// into holistic security assessments.
787    #[test]
788    fn test_constant_time_results() {
789        let results = ConstantTimeResults {
790            bigint: ConstantTimeResult {
791                is_constant_time: true,
792                mean_time: Duration::from_nanos(100),
793                std_dev: Duration::from_nanos(5),
794                max_variation: Duration::from_nanos(10),
795                sample_count: 100,
796                confidence: 0.95,
797            },
798            field: ConstantTimeResult {
799                is_constant_time: true,
800                mean_time: Duration::from_nanos(200),
801                std_dev: Duration::from_nanos(8),
802                max_variation: Duration::from_nanos(15),
803                sample_count: 100,
804                confidence: 0.96,
805            },
806            scalar: ConstantTimeResult {
807                is_constant_time: true,
808                mean_time: Duration::from_nanos(180),
809                std_dev: Duration::from_nanos(6),
810                max_variation: Duration::from_nanos(12),
811                sample_count: 100,
812                confidence: 0.94,
813            },
814        };
815
816        assert!(results.all_constant_time());
817        assert!(results.overall_confidence() > 0.9);
818    }
819}