1 // Copyright 2015-2019 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 crate::{digest, error, limb};
16 use core::convert::TryInto;
17 
18 #[repr(transparent)]
19 pub struct Scalar([u8; SCALAR_LEN]);
20 
21 pub const SCALAR_LEN: usize = 32;
22 
23 impl Scalar {
24     // Constructs a `Scalar` from `bytes`, failing if `bytes` encodes a scalar
25     // that not in the range [0, n).
from_bytes_checked(bytes: [u8; SCALAR_LEN]) -> Result<Self, error::Unspecified>26     pub fn from_bytes_checked(bytes: [u8; SCALAR_LEN]) -> Result<Self, error::Unspecified> {
27         const ORDER: [limb::Limb; SCALAR_LEN / limb::LIMB_BYTES] =
28             limbs![0x5cf5d3ed, 0x5812631a, 0xa2f79cd6, 0x14def9de, 0, 0, 0, 0x10000000];
29 
30         // `bytes` is in little-endian order.
31         let mut reversed = bytes;
32         reversed.reverse();
33 
34         let mut limbs = [0; SCALAR_LEN / limb::LIMB_BYTES];
35         limb::parse_big_endian_in_range_and_pad_consttime(
36             untrusted::Input::from(&reversed),
37             limb::AllowZero::Yes,
38             &ORDER,
39             &mut limbs,
40         )?;
41 
42         Ok(Self(bytes))
43     }
44 
45     // Constructs a `Scalar` from `digest` reduced modulo n.
from_sha512_digest_reduced(digest: digest::Digest) -> Self46     pub fn from_sha512_digest_reduced(digest: digest::Digest) -> Self {
47         extern "C" {
48             fn GFp_x25519_sc_reduce(s: &mut UnreducedScalar);
49         }
50         let mut unreduced = [0u8; digest::SHA512_OUTPUT_LEN];
51         unreduced.copy_from_slice(digest.as_ref());
52         unsafe { GFp_x25519_sc_reduce(&mut unreduced) };
53         Self((&unreduced[..SCALAR_LEN]).try_into().unwrap())
54     }
55 }
56 
57 #[repr(transparent)]
58 pub struct MaskedScalar([u8; SCALAR_LEN]);
59 
60 impl MaskedScalar {
from_bytes_masked(bytes: [u8; SCALAR_LEN]) -> Self61     pub fn from_bytes_masked(bytes: [u8; SCALAR_LEN]) -> Self {
62         extern "C" {
GFp_x25519_sc_mask(a: &mut [u8; SCALAR_LEN])63             fn GFp_x25519_sc_mask(a: &mut [u8; SCALAR_LEN]);
64         }
65         let mut r = Self(bytes);
66         unsafe { GFp_x25519_sc_mask(&mut r.0) };
67         r
68     }
69 }
70 
71 impl From<MaskedScalar> for Scalar {
from(MaskedScalar(scalar): MaskedScalar) -> Self72     fn from(MaskedScalar(scalar): MaskedScalar) -> Self {
73         Self(scalar)
74     }
75 }
76 
77 type UnreducedScalar = [u8; UNREDUCED_SCALAR_LEN];
78 const UNREDUCED_SCALAR_LEN: usize = SCALAR_LEN * 2;
79