1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! Personality typestate: a zero-size marker that selects which implementation
//! of an operation is picked at monomorphization.
//!
//! Two personalities ship here:
//!
//! - [`Nct`] (default): standard "non-constant-time" implementation.
//! - [`Ct`]: constant-time implementation. Slower bodies whose timing is
//! independent of operand values, defensible against an adversarial
//! optimizer. Used by signing paths and any code handling secret values.
//!
//! This is a pure-`core` marker (it depends only on [`PhantomData`]); it is
//! deliberately **not** gated behind the `ct` feature, which governs only the
//! `subtle`-backed constant-time *implementations*. It is intended to apply to
//! this crate's numeric operations, but nothing about the marker itself is
//! numeric — if a non-numeric consumer ever needs it, lifting it into its own
//! crate (re-exported here) is mechanical.
//!
//! ## Const-eval dispatch via `match P::TAG`
//!
//! Composite `const fn` methods that need to dispatch on personality can
//! `match` on the [`PersonalityTag`] associated constant:
//!
//! ```ignore
//! const fn dispatched<P: Personality>(x: u32) -> u32 {
//! match P::TAG {
//! PersonalityTag::Nct => fast_body(x),
//! PersonalityTag::Ct => ct_body(x),
//! }
//! }
//! ```
//!
//! Trait *method* calls (e.g. `P::widening_mul(x, y)`) require unstable
//! `const_trait_impl` in const contexts and are not used by this pattern. Tag
//! dispatch works on stable today and composes through multi-level generic
//! `const fn` chains without loss of const-eval.
use PhantomData;
/// Marker trait for personalities. Sealed — implementations live in this
/// crate. Downstream code uses the [`Nct`] and [`Ct`] types directly or
/// writes `match P::TAG` dispatch using [`PersonalityTag`].
/// Compile-time tag identifying the active personality. Returned by
/// [`Personality::TAG`] and used as the discriminant for `match P::TAG`
/// dispatch in `const fn` bodies.
/// Non-constant-time marker. The default personality.
;
/// Constant-time marker.
///
/// Selects constant-time implementations of operation primitives — bodies
/// whose execution time and memory access pattern do not depend on operand
/// values. Appropriate for code that handles secret values, where
/// operand-dependent timing or memory access would leak them.
///
/// Constant-time-only APIs (e.g. `subtle::ConditionallySelectable`,
/// `ConstantTimeEq`) should be exposed only for the `Ct` variant — wrong-
/// variant calls then become compile errors, not silent non-constant-time
/// execution.
;
/// `PhantomData` helper for storing a personality marker as a zero-size field.
/// Use as `_p: PersonalityMarker<P>` in struct definitions.
pub type PersonalityMarker<P> = ;
/// Projects a carrier type's [`Personality`] at the type level.
///
/// Implemented by carrier types whose implementation shape is selected
/// by a personality parameter (a bigint parameterized over its
/// personality projects that parameter), and by the primitive integers,
/// which project [`Nct`]: they expose a single hardware-backed
/// implementation, select no constant-time variant, and make no
/// constant-time guarantee — integer division in particular has
/// operand-dependent latency on common CPUs.
///
/// Consumers bound on the projection to gate algorithm choice by
/// personality: `T: HasPersonality<P = Nct>` admits a type into
/// variable-time code paths, `P = Ct` into constant-time-only ones.
/// The declaration is the carrier author's contract; there is no way
/// to verify it structurally.
impl_has_personality_nct!;