Skip to content

Commit

Permalink
Replace limbs initializer with const from_hex
Browse files Browse the repository at this point in the history
The current macro initializer is not uniform across architectures,
and doesn't work when the number of 64bit limbs is not exactly half
that of 32bit limbs, (i.e. 521 bit).
This change replaces all limbs! initializers with a new const
function with hex string initializers, which is more portable and
more ergonomic.
  • Loading branch information
vkrasnov committed Oct 6, 2023
1 parent 789ba20 commit b9e2b51
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 162 deletions.
5 changes: 3 additions & 2 deletions src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#[macro_use]
pub mod constant;
mod constant;

#[cfg(feature = "alloc")]
pub mod bigint;
Expand All @@ -26,3 +25,5 @@ mod nonnegative;

#[allow(dead_code)]
const BIGINT_MODULUS_MAX_LIMBS: usize = 8192 / crate::limb::LIMB_BITS;

pub use constant::limbs_from_hex;
33 changes: 23 additions & 10 deletions src/arithmetic/constant.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
#[cfg(target_pointer_width = "32")]
macro_rules! limbs {
( $($limb:expr),+ ) => {
[ $($limb),+ ]
};
use crate::limb::Limb;

const fn parse_digit(d: u8) -> u8 {
match d.to_ascii_lowercase() {
b'0'..=b'9' => d - b'0',
b'a'..=b'f' => d - b'a' + 10,
_ => panic!(),
}
}

#[cfg(target_pointer_width = "64")]
macro_rules! limbs {
( $($limb_lo:expr, $limb_hi:expr),+) => {
[ $((($limb_hi | 0u64) << 32) | $limb_lo),+ ]
};
// TODO: this would be nicer as a trait, but currently traits don't support const functions
pub const fn limbs_from_hex<const LIMBS: usize>(hex: &str) -> [Limb; LIMBS] {
let hex = hex.as_bytes();
let mut limbs = [0; LIMBS];
let limb_nibbles = core::mem::size_of::<Limb>() * 2;
let mut i = 0;

while i < hex.len() {
let char = hex[hex.len() - 1 - i];
let val = parse_digit(char);
limbs[i / limb_nibbles] |= (val as Limb) << ((i % limb_nibbles) * 4);
i += 1;
}

limbs
}
4 changes: 2 additions & 2 deletions src/ec/curve25519/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use crate::{digest, error, limb};
use crate::{arithmetic::limbs_from_hex, digest, error, limb};

#[repr(transparent)]
pub struct Scalar([u8; SCALAR_LEN]);
Expand All @@ -24,7 +24,7 @@ impl Scalar {
// that not in the range [0, n).
pub fn from_bytes_checked(bytes: [u8; SCALAR_LEN]) -> Result<Self, error::Unspecified> {
const ORDER: [limb::Limb; SCALAR_LEN / limb::LIMB_BYTES] =
limbs![0x5cf5d3ed, 0x5812631a, 0xa2f79cd6, 0x14def9de, 0, 0, 0, 0x10000000];
limbs_from_hex("1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed");

// `bytes` is in little-endian order.
let mut reversed = bytes;
Expand Down
8 changes: 2 additions & 6 deletions src/ec/suite_b/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use crate::{arithmetic::montgomery::*, c, error, limb::*};
use crate::{arithmetic::limbs_from_hex, arithmetic::montgomery::*, c, error, limb::*};
use core::marker::PhantomData;

pub use self::elem::*;
Expand Down Expand Up @@ -50,11 +50,7 @@ impl Point {
}
}

static ONE: Elem<Unencoded> = Elem {
limbs: limbs![1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
m: PhantomData,
encoding: PhantomData,
};
const ONE: Elem<Unencoded> = Elem::from_hex("1");

/// Operations and values needed by all curve operations.
pub struct CommonOps {
Expand Down
13 changes: 12 additions & 1 deletion src/ec/suite_b/ops/elem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use crate::{
arithmetic::montgomery::{Encoding, ProductEncoding},
arithmetic::{
limbs_from_hex,
montgomery::{Encoding, ProductEncoding},
},
limb::{Limb, LIMB_BITS},
};
use core::marker::PhantomData;
Expand Down Expand Up @@ -44,6 +47,14 @@ impl<M, E: Encoding> Elem<M, E> {
encoding: PhantomData,
}
}

pub const fn from_hex(hex: &str) -> Self {
Elem {
limbs: limbs_from_hex(hex),
m: PhantomData,
encoding: PhantomData,
}
}
}

#[inline]
Expand Down
74 changes: 11 additions & 63 deletions src/ec/suite_b/ops/p256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,53 +16,17 @@ use super::{
elem::{binary_op, binary_op_assign},
elem_sqr_mul, elem_sqr_mul_acc, Modulus, *,
};
use core::marker::PhantomData;

macro_rules! p256_limbs {
[ $($limb:expr),+ ] => {
limbs![$($limb),+, 0, 0, 0, 0]
};
}

pub static COMMON_OPS: CommonOps = CommonOps {
num_limbs: 256 / LIMB_BITS,

q: Modulus {
p: p256_limbs![
0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
0xffffffff
],
rr: p256_limbs![
0x00000003, 0x00000000, 0xffffffff, 0xfffffffb, 0xfffffffe, 0xffffffff, 0xfffffffd,
0x00000004
],
},

n: Elem {
limbs: p256_limbs![
0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, 0xffffffff, 0xffffffff, 0x00000000,
0xffffffff
],
m: PhantomData,
encoding: PhantomData, // Unencoded
},

a: Elem {
limbs: p256_limbs![
0xfffffffc, 0xffffffff, 0xffffffff, 0x00000003, 0x00000000, 0x00000000, 0x00000004,
0xfffffffc
],
m: PhantomData,
encoding: PhantomData, // R
},
b: Elem {
limbs: p256_limbs![
0x29c4bddf, 0xd89cdf62, 0x78843090, 0xacf005cd, 0xf7212ed6, 0xe5a220ab, 0x04874834,
0xdc30061d
],
m: PhantomData,
encoding: PhantomData, // R
p: limbs_from_hex("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"),
rr: limbs_from_hex("4fffffffdfffffffffffffffefffffffbffffffff0000000000000003"),
},
n: Elem::from_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"),
a: Elem::from_hex("fffffffc00000004000000000000000000000003fffffffffffffffffffffffc"),
b: Elem::from_hex("dc30061d04874834e5a220abf7212ed6acf005cd78843090d89cdf6229c4bddf"),

elem_mul_mont: p256_mul_mont,
elem_sqr_mont: p256_sqr_mont,
Expand Down Expand Up @@ -151,25 +115,15 @@ pub static PUBLIC_SCALAR_OPS: PublicScalarOps = PublicScalarOps {
scalar_ops: &SCALAR_OPS,
public_key_ops: &PUBLIC_KEY_OPS,
private_key_ops: &PRIVATE_KEY_OPS,

q_minus_n: Elem {
limbs: p256_limbs![0x039cdaae, 0x0c46353d, 0x58e8617b, 0x43190553, 0, 0, 0, 0],
m: PhantomData,
encoding: PhantomData, // Unencoded
},
q_minus_n: Elem::from_hex("4319055358e8617b0c46353d039cdaae"),
};

pub static PRIVATE_SCALAR_OPS: PrivateScalarOps = PrivateScalarOps {
scalar_ops: &SCALAR_OPS,

oneRR_mod_n: Scalar {
limbs: p256_limbs![
0xbe79eea2, 0x83244c95, 0x49bd6fa6, 0x4699799c, 0x2b6bec59, 0x2845b239, 0xf3d95620,
0x66e12d94
],
m: PhantomData,
encoding: PhantomData, // R
},
oneRR_mod_n: Scalar::from_hex(
"66e12d94f3d956202845b2392b6bec594699799c49bd6fa683244c95be79eea2",
),
};

fn p256_scalar_inv_to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
Expand Down Expand Up @@ -210,14 +164,8 @@ fn p256_scalar_inv_to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
}

fn to_mont(a: &Scalar) -> Scalar<R> {
static N_RR: Scalar<Unencoded> = Scalar {
limbs: p256_limbs![
0xbe79eea2, 0x83244c95, 0x49bd6fa6, 0x4699799c, 0x2b6bec59, 0x2845b239, 0xf3d95620,
0x66e12d94
],
m: PhantomData,
encoding: PhantomData,
};
const N_RR: Scalar<Unencoded> =
Scalar::from_hex("66e12d94f3d956202845b2392b6bec594699799c49bd6fa683244c95be79eea2");
binary_op(p256_scalar_mul_mont, a, &N_RR)
}

Expand Down
93 changes: 15 additions & 78 deletions src/ec/suite_b/ops/p384.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,54 +12,24 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use crate::arithmetic::limbs_from_hex;

use super::{
elem::{binary_op, binary_op_assign},
elem_sqr_mul, elem_sqr_mul_acc, Modulus, *,
};
use core::marker::PhantomData;

macro_rules! p384_limbs {
[$($limb:expr),+] => {
limbs![$($limb),+]
};
}

pub static COMMON_OPS: CommonOps = CommonOps {
num_limbs: 384 / LIMB_BITS,

q: Modulus {
p: p384_limbs![
0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
],
rr: p384_limbs![1, 0xfffffffe, 0, 2, 0, 0xfffffffe, 0, 2, 1, 0, 0, 0],
},
n: Elem {
limbs: p384_limbs![
0xccc52973, 0xecec196a, 0x48b0a77a, 0x581a0db2, 0xf4372ddf, 0xc7634d81, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
],
m: PhantomData,
encoding: PhantomData, // Unencoded
},

a: Elem {
limbs: p384_limbs![
0xfffffffc, 0x00000003, 0x00000000, 0xfffffffc, 0xfffffffb, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
],
m: PhantomData,
encoding: PhantomData, // Unreduced
p: limbs_from_hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff"),
rr: limbs_from_hex("10000000200000000fffffffe000000000000000200000000fffffffe00000001"),
},
b: Elem {
limbs: p384_limbs![
0x9d412dcc, 0x08118871, 0x7a4c32ec, 0xf729add8, 0x1920022e, 0x77f2209b, 0x94938ae2,
0xe3374bee, 0x1f022094, 0xb62b21f4, 0x604fbff9, 0xcd08114b
],
m: PhantomData,
encoding: PhantomData, // Unreduced
},

n: Elem::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973"),
a: Elem::from_hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc0000000000000003fffffffc"),
b: Elem::from_hex("cd08114b604fbff9b62b21f41f022094e3374bee94938ae277f2209b1920022ef729add87a4c32ec081188719d412dcc")
,
elem_mul_mont: p384_elem_mul_mont,
elem_sqr_mont: p384_elem_sqr_mont,

Expand Down Expand Up @@ -131,23 +101,9 @@ fn p384_elem_inv_squared(a: &Elem<R>) -> Elem<R> {

fn p384_point_mul_base_impl(a: &Scalar) -> Point {
// XXX: Not efficient. TODO: Precompute multiples of the generator.
static GENERATOR: (Elem<R>, Elem<R>) = (
Elem {
limbs: p384_limbs![
0x49c0b528, 0x3dd07566, 0xa0d6ce38, 0x20e378e2, 0x541b4d6e, 0x879c3afc, 0x59a30eff,
0x64548684, 0x614ede2b, 0x812ff723, 0x299e1513, 0x4d3aadc2
],
m: PhantomData,
encoding: PhantomData,
},
Elem {
limbs: p384_limbs![
0x4b03a4fe, 0x23043dad, 0x7bb4a9ac, 0xa1bfa8bf, 0x2e83b050, 0x8bade756, 0x68f4ffd9,
0xc6c35219, 0x3969a840, 0xdd800226, 0x5a15c5e9, 0x2b78abc2
],
m: PhantomData,
encoding: PhantomData,
},
const GENERATOR: (Elem<R>, Elem<R>) = (
Elem::from_hex("4d3aadc2299e1513812ff723614ede2b6454868459a30eff879c3afc541b4d6e20e378e2a0d6ce383dd0756649c0b528"),
Elem::from_hex("2b78abc25a15c5e9dd8002263969a840c6c3521968f4ffd98bade7562e83b050a1bfa8bf7bb4a9ac23043dad4b03a4fe"),
);

PRIVATE_KEY_OPS.point_mul(a, &GENERATOR)
Expand All @@ -168,25 +124,13 @@ pub static PUBLIC_SCALAR_OPS: PublicScalarOps = PublicScalarOps {
public_key_ops: &PUBLIC_KEY_OPS,
private_key_ops: &PRIVATE_KEY_OPS,

q_minus_n: Elem {
limbs: p384_limbs![
0x333ad68c, 0x1313e696, 0xb74f5885, 0xa7e5f24c, 0x0bc8d21f, 0x389cb27e, 0, 0, 0, 0, 0,
0
],

m: PhantomData,
encoding: PhantomData, // Unencoded
},
q_minus_n: Elem::from_hex("389cb27e0bc8d21fa7e5f24cb74f58851313e696333ad68c"),
};

pub static PRIVATE_SCALAR_OPS: PrivateScalarOps = PrivateScalarOps {
scalar_ops: &SCALAR_OPS,

oneRR_mod_n: Scalar {
limbs: N_RR_LIMBS,
m: PhantomData,
encoding: PhantomData, // R
},
oneRR_mod_n: Scalar::from_hex(N_RR_HEX),
};

fn p384_scalar_inv_to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
Expand Down Expand Up @@ -232,11 +176,7 @@ fn p384_scalar_inv_to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
}

fn to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
static N_RR: Scalar<Unencoded> = Scalar {
limbs: N_RR_LIMBS,
m: PhantomData,
encoding: PhantomData,
};
const N_RR: Scalar<Unencoded> = Scalar::from_hex(N_RR_HEX);
binary_op(p384_scalar_mul_mont, a, &N_RR)
}

Expand Down Expand Up @@ -332,10 +272,7 @@ unsafe extern "C" fn p384_elem_sqr_mont(
p384_elem_mul_mont(r, a, a);
}

const N_RR_LIMBS: [Limb; MAX_LIMBS] = p384_limbs![
0x19b409a9, 0x2d319b24, 0xdf1aa419, 0xff3d81e5, 0xfcb82947, 0xbc3e483a, 0x4aab1cc5, 0xd40d4917,
0x28266895, 0x3fb05b7a, 0x2b39bf21, 0x0c84ee01
];
const N_RR_HEX: &str = "0c84ee012b39bf213fb05b7a28266895d40d49174aab1cc5bc3e483afcb82947ff3d81e5df1aa4192d319b2419b409a9";

prefixed_extern! {
fn p384_elem_mul_mont(
Expand Down

0 comments on commit b9e2b51

Please sign in to comment.