Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions k256/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ elliptic-curve = { version = "= 0.5.0-pre", default-features = false, features =
sha2 = { version = "0.9", optional = true, default-features = false }

[dev-dependencies]
criterion = "0.3"
ecdsa-core = { version = "= 0.7.0-pre", package = "ecdsa", default-features = false, features = ["dev"] }
hex = "0.4" # TODO: switch to hex-literal
hex-literal = "0.2"
proptest = "0.10"
num-bigint = "0.3"
num-traits = "0.2"
criterion = "0.3"
proptest = "0.10"
rand_core = { version = "0.5", features = ["getrandom"] }

[features]
default = ["arithmetic", "oid", "std"]
Expand Down
11 changes: 11 additions & 0 deletions k256/src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ use crate::{CompressedPoint, PublicKey, Secp256k1, UncompressedPoint};
use field::FieldElement;
use scalar::{NonZeroScalar, Scalar};

#[cfg(feature = "zeroize")]
use elliptic_curve::zeroize::Zeroize;

const CURVE_EQUATION_B_SINGLE: u32 = 7u32;

#[rustfmt::skip]
Expand Down Expand Up @@ -205,6 +208,14 @@ impl FromPublicKey<Secp256k1> for AffinePoint {
}
}

#[cfg(feature = "zeroize")]
impl Zeroize for AffinePoint {
fn zeroize(&mut self) {
self.x.zeroize();
self.y.zeroize();
}
}

/// A point on the secp256k1 curve in projective coordinates.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
Expand Down
10 changes: 10 additions & 0 deletions k256/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ use crate::ElementBytes;
use core::ops::{Add, AddAssign, Mul, MulAssign};
use elliptic_curve::subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

#[cfg(feature = "zeroize")]
use elliptic_curve::zeroize::Zeroize;

#[cfg(test)]
use num_bigint::{BigUint, ToBigUint};

Expand Down Expand Up @@ -292,6 +295,13 @@ impl MulAssign<FieldElement> for FieldElement {
}
}

#[cfg(feature = "zeroize")]
impl Zeroize for FieldElement {
fn zeroize(&mut self) {
self.0.zeroize();
}
}

#[cfg(test)]
mod tests {
use num_bigint::{BigUint, ToBigUint};
Expand Down
10 changes: 10 additions & 0 deletions k256/src/arithmetic/field/field_10x26.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
use crate::ElementBytes;
use elliptic_curve::subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

#[cfg(feature = "zeroize")]
use elliptic_curve::zeroize::Zeroize;

/// Scalars modulo SECP256k1 modulus (2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1).
/// Uses 10 32-bit limbs (little-endian), where in the normalized form
/// first 9 contain 26 bits of the value each, and the last one contains 22 bits.
Expand Down Expand Up @@ -696,3 +699,10 @@ impl ConstantTimeEq for FieldElement10x26 {
& self.0[9].ct_eq(&other.0[9])
}
}

#[cfg(feature = "zeroize")]
impl Zeroize for FieldElement10x26 {
fn zeroize(&mut self) {
self.0.zeroize();
}
}
10 changes: 10 additions & 0 deletions k256/src/arithmetic/field/field_5x52.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
use crate::ElementBytes;
use elliptic_curve::subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

#[cfg(feature = "zeroize")]
use elliptic_curve::zeroize::Zeroize;

/// Scalars modulo SECP256k1 modulus (2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1).
/// Uses 5 64-bit limbs (little-endian), where in the normalized form
/// first 4 contain 52 bits of the value each, and the last one contains 48 bits.
Expand Down Expand Up @@ -483,3 +486,10 @@ impl ConstantTimeEq for FieldElement5x52 {
& self.0[4].ct_eq(&other.0[4])
}
}

#[cfg(feature = "zeroize")]
impl Zeroize for FieldElement5x52 {
fn zeroize(&mut self) {
self.0.zeroize();
}
}
12 changes: 12 additions & 0 deletions k256/src/arithmetic/field/field_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use crate::ElementBytes;
use elliptic_curve::subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use cfg_if::cfg_if;

#[cfg(feature = "zeroize")]
use elliptic_curve::zeroize::Zeroize;

cfg_if! {
if #[cfg(any(target_pointer_width = "32", feature = "force-32-bit"))] {
use super::field_10x26::FieldElement10x26 as FieldElementUnsafeImpl;
Expand Down Expand Up @@ -158,3 +161,12 @@ impl ConstantTimeEq for FieldElementImpl {
& Choice::from((self.normalized == other.normalized) as u8)
}
}

#[cfg(feature = "zeroize")]
impl Zeroize for FieldElementImpl {
fn zeroize(&mut self) {
self.value.zeroize();
self.magnitude.zeroize();
self.normalized.zeroize();
}
}
10 changes: 10 additions & 0 deletions k256/src/arithmetic/field/field_montgomery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
use elliptic_curve::subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use crate::{arithmetic::util::{adc64, mac64, mac64_typemax, sbb64}, ElementBytes};

#[cfg(feature = "zeroize")]
use elliptic_curve::zeroize::Zeroize;

const fn bytes_to_u64(b: &[u8; 8]) -> u64 {
((b[0] as u64) << 56)
| ((b[1] as u64) << 48)
Expand Down Expand Up @@ -411,3 +414,10 @@ impl Default for FieldElementMontgomery {
Self::zero()
}
}

#[cfg(feature = "zeroize")]
impl Zeroize for FieldElementMontgomery {
fn zeroize(&mut self) {
self.0.zeroize();
}
}
3 changes: 2 additions & 1 deletion k256/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
//! # {
//! use k256::{
//! ecdsa::{Signer, Signature, signature::RandomizedSigner},
//! elliptic_curve::{Generate, rand_core::OsRng},
//! elliptic_curve::{Generate},
//! SecretKey,
//! };
//! use rand_core::OsRng; // requires 'getrandom' feature
//!
//! // Signing
//! let secret_key = SecretKey::generate(&mut OsRng);
Expand Down
1 change: 1 addition & 0 deletions p256/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ecdsa-core = { version = "= 0.7.0-pre", package = "ecdsa", default-features = fa
hex = "0.4" # TODO: switch to hex-literal
hex-literal = "0.2"
proptest = "0.10"
rand_core = { version = "0.5", features = ["getrandom"] }

[features]
default = ["arithmetic", "std"]
Expand Down
11 changes: 11 additions & 0 deletions p256/src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ use crate::{CompressedPoint, NistP256, PublicKey, UncompressedPoint};
use field::{FieldElement, MODULUS};
use scalar::{NonZeroScalar, Scalar};

#[cfg(feature = "zeroize")]
use elliptic_curve::zeroize::Zeroize;

/// a = -3
const CURVE_EQUATION_A: FieldElement = FieldElement::zero()
.subtract(&FieldElement::one())
Expand Down Expand Up @@ -195,6 +198,14 @@ impl Neg for AffinePoint {
}
}

#[cfg(feature = "zeroize")]
impl Zeroize for AffinePoint {
fn zeroize(&mut self) {
self.x.zeroize();
self.y.zeroize();
}
}

/// A point on the secp256r1 curve in projective coordinates.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
Expand Down
10 changes: 10 additions & 0 deletions p256/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use elliptic_curve::subtle::{Choice, ConditionallySelectable, ConstantTimeEq, Ct
#[cfg(feature = "rand")]
use elliptic_curve::rand_core::{CryptoRng, RngCore};

#[cfg(feature = "zeroize")]
use elliptic_curve::zeroize::Zeroize;

use super::util::{adc, mac, sbb};

/// The number of 64-bit limbs used to represent a [`FieldElement`].
Expand Down Expand Up @@ -499,6 +502,13 @@ impl<'a> Neg for &'a FieldElement {
}
}

#[cfg(feature = "zeroize")]
impl Zeroize for FieldElement {
fn zeroize(&mut self) {
self.0.zeroize();
}
}

#[cfg(test)]
mod tests {
use super::FieldElement;
Expand Down
54 changes: 50 additions & 4 deletions p256/src/ecdsa.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,61 @@
//! Elliptic Curve Digital Signature Algorithm (ECDSA)
//!
//! This module contains support for computing and verifying ECDSA signatures.
//! To use it, you will need to enable one of the two following Cargo features:
//!
//! - `ecdsa-core`: provides only the [`Signature`] type (which represents an
//! ECDSA/P-256 signature). Does not require the `arithmetic` feature.
//! This is useful for 3rd-party crates which wish to use the `Signature`
//! type for interoperability purposes (particularly in conjunction with the
//! [`signature::Signer`] trait. Example use cases for this include other
//! software implementations of ECDSA/P-256 and wrappers for cloud KMS
//! services or hardware devices (HSM or crypto hardware wallet).
//! - `ecdsa`: provides the [`Signature`], [`Signer`], and [`Verifier`] types
//! which natively implement ECDSA/P-256 signing and verification.
//!
//! ## Signing/Verification Example
//!
//! This example requires the `ecdsa` Cargo feature is enabled:
//!
//! ```
//! # #[cfg(feature = "ecdsa")]
//! # {
//! use p256::{
//! ecdsa::{Signer, Signature, signature::RandomizedSigner},
//! elliptic_curve::{Generate},
//! SecretKey,
//! };
//! use rand_core::OsRng; // requires 'getrandom' feature
//!
//! // Signing
//! let secret_key = SecretKey::generate(&mut OsRng);
//! let signer = Signer::new(&secret_key).expect("secret key invalid");
//! let message = b"ECDSA proves knowledge of a secret number in the context of a single message";
//!
//! // Note: the signature type must be annotated or otherwise inferrable as
//! // `Signer` has many impls of the `RandomizedSigner` trait (for both
//! // regular and recoverable signature types).
//! let signature: Signature = signer.sign_with_rng(&mut OsRng, message);
//!
//! // Verification
//! use p256::{PublicKey, ecdsa::{Verifier, signature::Verifier as _}};
//!
//! let public_key = PublicKey::from_secret_key(&secret_key, true).expect("secret key invalid");
//! let verifier = Verifier::new(&public_key).expect("public key invalid");
//!
//! assert!(verifier.verify(message, &signature).is_ok());
//! # }
//! ```

pub use ecdsa_core::signature::{self, Error};

use super::NistP256;
use core::borrow::Borrow;

#[cfg(feature = "ecdsa")]
use {
crate::{AffinePoint, ElementBytes, ProjectivePoint, Scalar},
ecdsa_core::{
hazmat::{SignPrimitive, VerifyPrimitive},
Error,
},
ecdsa_core::hazmat::{SignPrimitive, VerifyPrimitive},
elliptic_curve::{ops::Invert, subtle::CtOption, FromBytes},
};

Expand Down