ring/arithmetic/bigint/
modulusvalue.rs

1// Copyright 2015-2024 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 AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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
15use super::{
16    super::{MAX_LIMBS, MIN_LIMBS},
17    BoxedLimbs, Modulus, PublicModulus,
18};
19use crate::{
20    bits::BitLength,
21    error,
22    limb::{self, Limb, LIMB_BYTES},
23};
24
25/// `OwnedModulus`, without the overhead of Montgomery multiplication support.
26pub(crate) struct OwnedModulusValue<M> {
27    limbs: BoxedLimbs<M>, // Also `value >= 3`.
28
29    len_bits: BitLength,
30}
31
32impl<M: PublicModulus> Clone for OwnedModulusValue<M> {
33    fn clone(&self) -> Self {
34        Self {
35            limbs: self.limbs.clone(),
36            len_bits: self.len_bits,
37        }
38    }
39}
40
41impl<M> OwnedModulusValue<M> {
42    pub(crate) fn from_be_bytes(input: untrusted::Input) -> Result<Self, error::KeyRejected> {
43        let num_limbs = (input.len() + LIMB_BYTES - 1) / LIMB_BYTES;
44        const _MODULUS_MIN_LIMBS_AT_LEAST_2: () = assert!(MIN_LIMBS >= 2);
45        if num_limbs < MIN_LIMBS {
46            return Err(error::KeyRejected::unexpected_error());
47        }
48        if num_limbs > MAX_LIMBS {
49            return Err(error::KeyRejected::too_large());
50        }
51        // The above implies n >= 3, so we don't need to check that.
52
53        // Reject leading zeros. Also reject the value zero ([0]) because zero
54        // isn't positive.
55        if untrusted::Reader::new(input).peek(0) {
56            return Err(error::KeyRejected::invalid_encoding());
57        }
58
59        let mut limbs = BoxedLimbs::zero(num_limbs);
60        limb::parse_big_endian_and_pad_consttime(input, &mut limbs)
61            .map_err(|error::Unspecified| error::KeyRejected::unexpected_error())?;
62        limb::limbs_reject_even_leak_bit(&limbs)
63            .map_err(|_: error::Unspecified| error::KeyRejected::invalid_component())?;
64
65        let len_bits = limb::limbs_minimal_bits(&limbs);
66
67        Ok(Self { limbs, len_bits })
68    }
69
70    pub fn verify_less_than<L>(&self, l: &Modulus<L>) -> Result<(), error::Unspecified> {
71        if self.len_bits() > l.len_bits() {
72            return Err(error::Unspecified);
73        }
74        if self.limbs.len() == l.limbs().len() {
75            limb::verify_limbs_less_than_limbs_leak_bit(&self.limbs, l.limbs())?;
76        }
77        Ok(())
78    }
79
80    pub fn len_bits(&self) -> BitLength {
81        self.len_bits
82    }
83
84    #[inline]
85    pub(super) fn limbs(&self) -> &[Limb] {
86        &self.limbs
87    }
88}