ring/ec/suite_b/ops/
elem.rs

1// Copyright 2017 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
15use crate::{
16    arithmetic::{
17        limbs_from_hex,
18        montgomery::{Encoding, ProductEncoding},
19    },
20    limb::{Limb, LIMB_BITS},
21};
22use core::marker::PhantomData;
23
24/// Elements of ℤ/mℤ for some modulus *m*. Elements are always fully reduced
25/// with respect to *m*; i.e. the 0 <= x < m for every value x.
26#[derive(Clone, Copy)]
27pub struct Elem<M, E: Encoding> {
28    // XXX: pub
29    pub(super) limbs: [Limb; MAX_LIMBS],
30
31    /// The modulus *m* for the ring ℤ/mℤ for which this element is a value.
32    pub(super) m: PhantomData<M>,
33
34    /// The number of Montgomery factors that need to be canceled out from
35    /// `value` to get the actual value.
36    pub(super) encoding: PhantomData<E>,
37}
38
39impl<M, E: Encoding> Elem<M, E> {
40    // There's no need to convert `value` to the Montgomery domain since
41    // 0 * R**2 (mod m) == 0, so neither the modulus nor the encoding are needed
42    // as inputs for constructing a zero-valued element.
43    pub fn zero() -> Self {
44        Self {
45            limbs: [0; MAX_LIMBS],
46            m: PhantomData,
47            encoding: PhantomData,
48        }
49    }
50
51    pub const fn from_hex(hex: &str) -> Self {
52        Elem {
53            limbs: limbs_from_hex(hex),
54            m: PhantomData,
55            encoding: PhantomData,
56        }
57    }
58}
59
60#[inline]
61pub fn mul_mont<M, EA: Encoding, EB: Encoding>(
62    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
63    a: &Elem<M, EA>,
64    b: &Elem<M, EB>,
65) -> Elem<M, <(EA, EB) as ProductEncoding>::Output>
66where
67    (EA, EB): ProductEncoding,
68{
69    binary_op(f, a, b)
70}
71
72// let r = f(a, b); return r;
73#[inline]
74pub fn binary_op<M, EA: Encoding, EB: Encoding, ER: Encoding>(
75    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
76    a: &Elem<M, EA>,
77    b: &Elem<M, EB>,
78) -> Elem<M, ER> {
79    let mut r = Elem {
80        limbs: [0; MAX_LIMBS],
81        m: PhantomData,
82        encoding: PhantomData,
83    };
84    unsafe { f(r.limbs.as_mut_ptr(), a.limbs.as_ptr(), b.limbs.as_ptr()) }
85    r
86}
87
88// a := f(a, b);
89#[inline]
90pub fn binary_op_assign<M, EA: Encoding, EB: Encoding>(
91    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
92    a: &mut Elem<M, EA>,
93    b: &Elem<M, EB>,
94) {
95    unsafe { f(a.limbs.as_mut_ptr(), a.limbs.as_ptr(), b.limbs.as_ptr()) }
96}
97
98// let r = f(a); return r;
99#[inline]
100pub fn unary_op<M, E: Encoding>(
101    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
102    a: &Elem<M, E>,
103) -> Elem<M, E> {
104    let mut r = Elem {
105        limbs: [0; MAX_LIMBS],
106        m: PhantomData,
107        encoding: PhantomData,
108    };
109    unsafe { f(r.limbs.as_mut_ptr(), a.limbs.as_ptr()) }
110    r
111}
112
113// a := f(a);
114#[inline]
115pub fn unary_op_assign<M, E: Encoding>(
116    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
117    a: &mut Elem<M, E>,
118) {
119    unsafe { f(a.limbs.as_mut_ptr(), a.limbs.as_ptr()) }
120}
121
122// a := f(a, a);
123#[inline]
124pub fn unary_op_from_binary_op_assign<M, E: Encoding>(
125    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
126    a: &mut Elem<M, E>,
127) {
128    unsafe { f(a.limbs.as_mut_ptr(), a.limbs.as_ptr(), a.limbs.as_ptr()) }
129}
130
131pub const MAX_LIMBS: usize = (384 + (LIMB_BITS - 1)) / LIMB_BITS;