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