ec suite_b: Calculate elem/scalar byte length in one place.

This commit is contained in:
Brian Smith 2023-12-03 11:18:25 -08:00
parent 16c3e19f71
commit 2926ebb500
3 changed files with 23 additions and 33 deletions

View File

@ -14,7 +14,7 @@
//! ECDSA Signatures using the P-256 and P-384 curves.
use crate::{digest, ec::suite_b::ops::*, limb::LIMB_BYTES};
use crate::{digest, ec::suite_b::ops::*};
/// Calculate the digest of `msg` using the digest algorithm `digest_alg`. Then
/// convert the digest to a scalar in the range [0, n) as described in
@ -54,16 +54,15 @@ pub(crate) fn digest_bytes_scalar(ops: &ScalarOps, digest: &[u8]) -> Scalar {
// This is a separate function solely so that we can test specific digest
// values like all-zero values and values larger than `n`.
fn digest_scalar_(ops: &ScalarOps, digest: &[u8]) -> Scalar {
let cops = ops.common;
let num_limbs = cops.num_limbs;
let digest = if digest.len() > num_limbs * LIMB_BYTES {
&digest[..(num_limbs * LIMB_BYTES)]
let len = ops.scalar_bytes_len();
let digest = if digest.len() > len {
&digest[..len]
} else {
digest
};
scalar_parse_big_endian_partially_reduced_variable_consttime(
cops,
ops.common,
untrusted::Input::from(digest),
)
.unwrap()
@ -72,12 +71,7 @@ fn digest_scalar_(ops: &ScalarOps, digest: &[u8]) -> Scalar {
#[cfg(test)]
mod tests {
use super::digest_bytes_scalar;
use crate::{
digest,
ec::suite_b::ops::*,
limb::{self, LIMB_BYTES},
test,
};
use crate::{digest, ec::suite_b::ops::*, limb, test};
#[test]
fn test() {
@ -103,10 +97,7 @@ mod tests {
let num_limbs = ops.public_key_ops.common.num_limbs;
assert_eq!(input.len(), digest_alg.output_len());
assert_eq!(
output.len(),
ops.public_key_ops.common.num_limbs * LIMB_BYTES
);
assert_eq!(output.len(), ops.scalar_ops.scalar_bytes_len());
let expected = scalar_parse_big_endian_variable(
ops.public_key_ops.common,
@ -116,7 +107,6 @@ mod tests {
.unwrap();
let actual = digest_bytes_scalar(ops.scalar_ops, &input);
assert_eq!(actual.limbs[..num_limbs], expected.limbs[..num_limbs]);
Ok(())

View File

@ -67,6 +67,12 @@ pub struct CommonOps {
}
impl CommonOps {
// The length of a field element, which is the same as the length of a
// scalar, in bytes.
pub fn len(&self) -> usize {
self.num_limbs * LIMB_BYTES
}
#[inline]
pub fn elem_add<E: Encoding>(&self, a: &mut Elem<E>, b: &Elem<E>) {
let num_limbs = self.num_limbs;
@ -213,7 +219,7 @@ impl PublicKeyOps {
// implements NIST SP 800-56A Step 2: "Verify that xQ and yQ are integers
// in the interval [0, p-1] in the case that q is an odd prime p[.]"
pub fn elem_parse(&self, input: &mut untrusted::Reader) -> Result<Elem<R>, error::Unspecified> {
let encoded_value = input.read_bytes(self.common.num_limbs * LIMB_BYTES)?;
let encoded_value = input.read_bytes(self.common.len())?;
let parsed = elem_parse_big_endian_fixed_consttime(self.common, encoded_value)?;
let mut r = Elem::zero();
// Montgomery encode (elem_to_mont).
@ -241,7 +247,7 @@ pub struct ScalarOps {
impl ScalarOps {
// The (maximum) length of a scalar, not including any padding.
pub fn scalar_bytes_len(&self) -> usize {
self.common.num_limbs * LIMB_BYTES
self.common.len()
}
/// Returns the modular inverse of `a` (mod `n`). Panics of `a` is zero,
@ -407,7 +413,7 @@ fn parse_big_endian_fixed_consttime<M>(
allow_zero: AllowZero,
max_exclusive: &[Limb],
) -> Result<elem::Elem<M, Unencoded>, error::Unspecified> {
if bytes.len() != ops.num_limbs * LIMB_BYTES {
if bytes.len() != ops.len() {
return Err(error::Unspecified);
}
let mut r = elem::Elem::zero();
@ -928,9 +934,9 @@ mod tests {
let product = priv_ops.point_mul(&p_scalar, &p);
let mut actual_result = vec![4u8; 1 + (2 * (cops.num_limbs * LIMB_BYTES))];
let mut actual_result = vec![4u8; 1 + (2 * cops.len())];
{
let (x, y) = actual_result[1..].split_at_mut(cops.num_limbs * LIMB_BYTES);
let (x, y) = actual_result[1..].split_at_mut(cops.len());
super::super::private_key::big_endian_affine_from_jacobian(
priv_ops,
Some(x),
@ -1147,7 +1153,7 @@ mod tests {
name: &str,
) -> Vec<u8> {
let unpadded_bytes = test_case.consume_bytes(name);
let mut bytes = vec![0; (ops.num_limbs * LIMB_BYTES) - unpadded_bytes.len()];
let mut bytes = vec![0; ops.len() - unpadded_bytes.len()];
bytes.extend(&unpadded_bytes);
bytes
}

View File

@ -16,21 +16,15 @@
//! ECDSA signing).
use super::{ops::*, verify_affine_point_is_on_the_curve};
use crate::{
arithmetic::montgomery::R,
ec, error,
limb::{self, LIMB_BYTES},
rand,
};
use crate::{arithmetic::montgomery::R, ec, error, limb, rand};
/// Generates a random scalar in the range [1, n).
pub fn random_scalar(
ops: &PrivateKeyOps,
rng: &dyn rand::SecureRandom,
) -> Result<Scalar, error::Unspecified> {
let num_limbs = ops.common.num_limbs;
let mut bytes = [0; ec::SCALAR_MAX_BYTES];
let bytes = &mut bytes[..(num_limbs * LIMB_BYTES)];
let bytes = &mut bytes[..ops.common.len()];
generate_private_scalar_bytes(ops, rng, bytes)?;
scalar_from_big_endian_bytes(ops, bytes)
}
@ -99,7 +93,7 @@ pub fn check_scalar_big_endian_bytes(
ops: &PrivateKeyOps,
bytes: &[u8],
) -> Result<(), error::Unspecified> {
debug_assert_eq!(bytes.len(), ops.common.num_limbs * LIMB_BYTES);
debug_assert_eq!(bytes.len(), ops.common.len());
scalar_from_big_endian_bytes(ops, bytes).map(|_| ())
}
@ -135,7 +129,7 @@ pub fn public_from_private(
public_out: &mut [u8],
my_private_key: &ec::Seed,
) -> Result<(), error::Unspecified> {
let elem_and_scalar_bytes = ops.common.num_limbs * LIMB_BYTES;
let elem_and_scalar_bytes = ops.common.len();
debug_assert_eq!(public_out.len(), 1 + (2 * elem_and_scalar_bytes));
let my_private_key = private_key_as_scalar(ops, my_private_key);
let my_public_key = ops.point_mul_base(&my_private_key);