// Copyright 2015-2023 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use crate::{ bits, error, limb::{self, Limb, LimbMask, LIMB_BYTES}, }; use alloc::{boxed::Box, vec, vec::Vec}; /// Nonnegative integers. pub(crate) struct Nonnegative { limbs: Vec, } impl Nonnegative { pub fn from_be_bytes_with_bit_length( input: untrusted::Input, ) -> Result<(Self, bits::BitLength), error::Unspecified> { let mut limbs = vec![0; (input.len() + LIMB_BYTES - 1) / LIMB_BYTES]; // Rejects empty inputs. limb::parse_big_endian_and_pad_consttime(input, &mut limbs)?; while limbs.last() == Some(&0) { let _ = limbs.pop(); } let r_bits = limb::limbs_minimal_bits(&limbs); Ok((Self { limbs }, r_bits)) } #[inline] pub fn is_odd(&self) -> bool { limb::limbs_are_even_constant_time(&self.limbs) != LimbMask::True } pub fn verify_less_than(&self, other: &Self) -> Result<(), error::Unspecified> { if !greater_than(other, self) { return Err(error::Unspecified); } Ok(()) } #[inline] pub fn limbs(&self) -> &[Limb] { &self.limbs } #[inline] pub fn into_limbs(self) -> Box<[Limb]> { self.limbs.into_boxed_slice() } } // Returns a > b. fn greater_than(a: &Nonnegative, b: &Nonnegative) -> bool { if a.limbs.len() == b.limbs.len() { limb::limbs_less_than_limbs_vartime(&b.limbs, &a.limbs) } else { a.limbs.len() > b.limbs.len() } }