1 // Copyright 2015-2023 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 use super::{elem_add, elem_sub, limb, BoxedLimbs, Limb, LimbMask, Modulus, Prime};
16 use crate::error;
17 use alloc::boxed::Box;
18 
19 pub struct PrivateExponent {
20     limbs: Box<[Limb]>,
21 }
22 
23 impl PrivateExponent {
24     // `p` is the modulus for which the exponent is in the interval [1, `p` - 1).
from_be_bytes_padded<M>( input: untrusted::Input, p: &Modulus<M>, ) -> Result<Self, error::Unspecified>25     pub fn from_be_bytes_padded<M>(
26         input: untrusted::Input,
27         p: &Modulus<M>,
28     ) -> Result<Self, error::Unspecified> {
29         let dP = BoxedLimbs::from_be_bytes_padded_less_than(input, p)?;
30 
31         // Proof that `dP < p - 1`:
32         //
33         // If `dP < p` then either `dP == p - 1` or `dP < p - 1`. Since `p` is
34         // odd, `p - 1` is even. `d` is odd, and an odd number modulo an even
35         // number is odd. Therefore `dP` must be odd. But then it cannot be
36         // `p - 1` and so we know `dP < p - 1`.
37         //
38         // Further we know `dP != 0` because `dP` is not even.
39         if limb::limbs_are_even_constant_time(&dP) != LimbMask::False {
40             return Err(error::Unspecified);
41         }
42 
43         Ok(Self {
44             limbs: dP.into_limbs(),
45         })
46     }
47 
48     #[cfg(test)]
from_be_bytes_for_test_only<M>( input: untrusted::Input, p: &Modulus<M>, ) -> Result<Self, error::Unspecified>49     pub fn from_be_bytes_for_test_only<M>(
50         input: untrusted::Input,
51         p: &Modulus<M>,
52     ) -> Result<Self, error::Unspecified> {
53         // Do exactly what `from_be_bytes_padded` does for any inputs it accepts.
54         if let r @ Ok(_) = Self::from_be_bytes_padded(input, p) {
55             return r;
56         }
57 
58         let dP = BoxedLimbs::<M>::positive_minimal_width_from_be_bytes(input)?;
59 
60         Ok(Self {
61             limbs: dP.into_limbs(),
62         })
63     }
64 
65     #[inline]
limbs(&self) -> &[Limb]66     pub(super) fn limbs(&self) -> &[Limb] {
67         &self.limbs
68     }
69 
70     // Returns `p - 2`.
for_flt<P: Prime>(p: &Modulus<P>) -> Self71     pub(super) fn for_flt<P: Prime>(p: &Modulus<P>) -> Self {
72         let two = elem_add(p.one(), p.one(), p);
73         let p_minus_2 = elem_sub(p.zero(), &two, p);
74         Self {
75             limbs: p_minus_2.limbs.into_limbs(),
76         }
77     }
78 }
79