Skip to main content

vsss_rs/
util.rs

1/*
2    Copyright Michael Lodder. All Rights Reserved.
3    SPDX-License-Identifier: Apache-2.0
4*/
5
6/// A trait for constant time indicating if a value is zero.
7pub trait CtIsZero {
8    /// Returns a `subtle::Choice` indicating if the value is zero.
9    /// Returns 1 if the value is zero, otherwise 0.
10    fn ct_is_zero(&self) -> subtle::Choice;
11}
12
13/// A trait for constant time indicating if a value is not zero.
14pub trait CtIsNotZero {
15    /// Returns a `subtle::Choice` indicating if the value is not zero.
16    /// Returns 1 if the value is not zero, otherwise 0.
17    fn ct_is_not_zero(&self) -> subtle::Choice;
18}
19
20impl CtIsZero for &[u8] {
21    fn ct_is_zero(&self) -> subtle::Choice {
22        let mut t = 0i8;
23        for b in *self {
24            t |= *b as i8;
25        }
26        t.ct_is_zero()
27    }
28}
29
30impl CtIsZero for [u8] {
31    fn ct_is_zero(&self) -> subtle::Choice {
32        let mut t = 0i8;
33        for b in self {
34            t |= *b as i8;
35        }
36        t.ct_is_zero()
37    }
38}
39
40impl CtIsZero for u8 {
41    fn ct_is_zero(&self) -> subtle::Choice {
42        let t = *self as i8;
43        let a = ((t | t.wrapping_neg()) >> 7) + 1;
44        subtle::Choice::from(a as u8)
45    }
46}
47
48impl CtIsZero for i8 {
49    fn ct_is_zero(&self) -> subtle::Choice {
50        let t = *self;
51        let a = ((t | t.wrapping_neg()) >> 7) + 1;
52        subtle::Choice::from(a as u8)
53    }
54}
55
56impl CtIsZero for u16 {
57    fn ct_is_zero(&self) -> subtle::Choice {
58        let t = *self as i16;
59        let a = ((t | t.wrapping_neg()) >> 15) + 1;
60        subtle::Choice::from(a as u8)
61    }
62}
63
64impl CtIsZero for i16 {
65    fn ct_is_zero(&self) -> subtle::Choice {
66        let t = *self;
67        let a = ((t | t.wrapping_neg()) >> 15) + 1;
68        subtle::Choice::from(a as u8)
69    }
70}
71
72impl CtIsZero for u32 {
73    fn ct_is_zero(&self) -> subtle::Choice {
74        let t = *self as i32;
75        let a = ((t | t.wrapping_neg()) >> 31) + 1;
76        subtle::Choice::from(a as u8)
77    }
78}
79
80impl CtIsZero for i32 {
81    fn ct_is_zero(&self) -> subtle::Choice {
82        let t = *self;
83        let a = ((t | t.wrapping_neg()) >> 31) + 1;
84        subtle::Choice::from(a as u8)
85    }
86}
87
88impl CtIsZero for u64 {
89    fn ct_is_zero(&self) -> subtle::Choice {
90        let t = *self as i64;
91        let a = ((t | t.wrapping_neg()) >> 63) + 1;
92        subtle::Choice::from(a as u8)
93    }
94}
95
96impl CtIsZero for i64 {
97    fn ct_is_zero(&self) -> subtle::Choice {
98        let t = *self;
99        let a = ((t | t.wrapping_neg()) >> 63) + 1;
100        subtle::Choice::from(a as u8)
101    }
102}
103
104#[cfg(target_pointer_width = "64")]
105impl CtIsZero for u128 {
106    fn ct_is_zero(&self) -> subtle::Choice {
107        let t = *self as i128;
108        let a = ((t | t.wrapping_neg()) >> 127) + 1;
109        subtle::Choice::from(a as u8)
110    }
111}
112
113#[cfg(target_pointer_width = "64")]
114impl CtIsZero for i128 {
115    fn ct_is_zero(&self) -> subtle::Choice {
116        let t = *self;
117        let a = ((t | t.wrapping_neg()) >> 127) + 1;
118        subtle::Choice::from(a as u8)
119    }
120}
121
122impl CtIsZero for usize {
123    fn ct_is_zero(&self) -> subtle::Choice {
124        let t = *self as isize;
125        let a = ((t | t.wrapping_neg()) >> (usize::BITS - 1)) + 1;
126        subtle::Choice::from(a as u8)
127    }
128}
129
130impl CtIsNotZero for &[u8] {
131    fn ct_is_not_zero(&self) -> subtle::Choice {
132        let mut t = 0i8;
133        for b in *self {
134            t |= *b as i8;
135        }
136        t.ct_is_not_zero()
137    }
138}
139
140impl CtIsNotZero for [u8] {
141    fn ct_is_not_zero(&self) -> subtle::Choice {
142        let mut t = 0i8;
143        for b in self {
144            t |= *b as i8;
145        }
146        t.ct_is_not_zero()
147    }
148}
149
150impl CtIsNotZero for u8 {
151    fn ct_is_not_zero(&self) -> subtle::Choice {
152        let t = *self as i8;
153        let a = ((t | t.wrapping_neg()) >> 7).wrapping_neg();
154        subtle::Choice::from(a as u8)
155    }
156}
157
158impl CtIsNotZero for i8 {
159    fn ct_is_not_zero(&self) -> subtle::Choice {
160        let t = *self;
161        let a = ((t | t.wrapping_neg()) >> 7).wrapping_neg();
162        subtle::Choice::from(a as u8)
163    }
164}
165
166impl CtIsNotZero for u16 {
167    fn ct_is_not_zero(&self) -> subtle::Choice {
168        let t = *self as i16;
169        let a = ((t | t.wrapping_neg()) >> 15).wrapping_neg();
170        subtle::Choice::from(a as u8)
171    }
172}
173
174impl CtIsNotZero for i16 {
175    fn ct_is_not_zero(&self) -> subtle::Choice {
176        let t = *self;
177        let a = ((t | t.wrapping_neg()) >> 15).wrapping_neg();
178        subtle::Choice::from(a as u8)
179    }
180}
181
182impl CtIsNotZero for u32 {
183    fn ct_is_not_zero(&self) -> subtle::Choice {
184        let t = *self as i32;
185        let a = ((t | t.wrapping_neg()) >> 31).wrapping_neg();
186        subtle::Choice::from(a as u8)
187    }
188}
189
190impl CtIsNotZero for i32 {
191    fn ct_is_not_zero(&self) -> subtle::Choice {
192        let t = *self;
193        let a = ((t | t.wrapping_neg()) >> 31).wrapping_neg();
194        subtle::Choice::from(a as u8)
195    }
196}
197
198impl CtIsNotZero for u64 {
199    fn ct_is_not_zero(&self) -> subtle::Choice {
200        let t = *self as i64;
201        let a = ((t | t.wrapping_neg()) >> 63).wrapping_neg();
202        subtle::Choice::from(a as u8)
203    }
204}
205
206impl CtIsNotZero for i64 {
207    fn ct_is_not_zero(&self) -> subtle::Choice {
208        let t = *self;
209        let a = ((t | t.wrapping_neg()) >> 63).wrapping_neg();
210        subtle::Choice::from(a as u8)
211    }
212}
213
214#[cfg(target_pointer_width = "64")]
215impl CtIsNotZero for u128 {
216    fn ct_is_not_zero(&self) -> subtle::Choice {
217        let t = *self as i128;
218        let a = ((t | t.wrapping_neg()) >> 127).wrapping_neg();
219        subtle::Choice::from(a as u8)
220    }
221}
222
223#[cfg(target_pointer_width = "64")]
224impl CtIsNotZero for i128 {
225    fn ct_is_not_zero(&self) -> subtle::Choice {
226        let t = *self;
227        let a = ((t | t.wrapping_neg()) >> 127).wrapping_neg();
228        subtle::Choice::from(a as u8)
229    }
230}
231
232impl CtIsNotZero for usize {
233    fn ct_is_not_zero(&self) -> subtle::Choice {
234        let t = *self as isize;
235        let a = ((t | t.wrapping_neg()) >> (usize::BITS - 1)).wrapping_neg();
236        subtle::Choice::from(a as u8)
237    }
238}