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
4 changes: 4 additions & 0 deletions crates/algorithms/curve25519/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

- [#1301](https://github.com/cryspen/libcrux/pull/1301): Expose scalar clamping and provide check for clamped-ness

## [0.0.5] (2026-01-22)

- [#1297](https://github.com/cryspen/libcrux/pull/1297): Update dependencies
Expand Down
11 changes: 10 additions & 1 deletion crates/algorithms/curve25519/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,18 @@ impl libcrux_traits::kem::arrayref::Kem<DK_LEN, EK_LEN, EK_LEN, SS_LEN, DK_LEN,
libcrux_traits::kem::slice::impl_trait!(X25519 => EK_LEN, DK_LEN, EK_LEN, EK_LEN, DK_LEN, DK_LEN);

/// Clamp a scalar.
fn clamp(scalar: &mut [u8; DK_LEN]) {
pub fn clamp(scalar: &mut [u8; DK_LEN]) {
// We clamp the key already to make sure it can't be misused.
scalar[0] &= 248u8;
scalar[31] &= 127u8;
scalar[31] |= 64u8;
}

/// Test whether a scalar is already clamped, error indicating that it is not.
pub fn is_clamped(scalar: &[u8; DK_LEN]) -> Result<(), Error> {
if scalar[0] & 7 != 0 || scalar[31] & 128 != 0 || scalar[31] & 64 != 64 {
Err(Error)
} else {
Ok(())
}
}
4 changes: 4 additions & 0 deletions libcrux-ecdh/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

- [#1301](https://github.com/cryspen/libcrux/pull/1301): Check length and clamping in X25519 secret validation

## [0.0.5] (2026-01-22)

- [#1297](https://github.com/cryspen/libcrux/pull/1297): Update dependencies
Expand Down
7 changes: 6 additions & 1 deletion libcrux-ecdh/src/ecdh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,12 @@ pub fn secret_to_public(alg: Algorithm, scalar: impl AsRef<[u8]>) -> Result<Vec<
pub fn validate_scalar(alg: Algorithm, s: impl AsRef<[u8]>) -> Result<(), Error> {
match alg {
Algorithm::X25519 => {
if s.as_ref().iter().all(|&b| b == 0) {
if s.as_ref().iter().all(|&b| b == 0)
|| libcrux_curve25519::is_clamped(
s.as_ref().try_into().map_err(|_| Error::InvalidScalar)?,
)
.is_err()
{
Err(Error::InvalidScalar)
} else {
Ok(())
Expand Down
1 change: 1 addition & 0 deletions libcrux-psq/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- [#1301](https://github.com/cryspen/libcrux/pull/1301): Fix broken clamping check for imported X25519 secret keys
- [#1307](https://github.com/cryspen/libcrux/pull/1307): Expose additional functionalities on the DHKEM (https://github.com/jstuczyn)
- [#1298](https://github.com/cryspen/libcrux/pull/1298): Propagate import/export functions from CMC crate (https://github.com/georgio)

Expand Down
2 changes: 1 addition & 1 deletion libcrux-psq/src/handshake/dhkem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl DHPrivateKey {
/// Import a Diffie-Hellman private key from raw bytes.
pub fn from_bytes(value: &[u8; 32]) -> Result<Self, Error> {
// Test whether the key is already clamped to make sure it can't be misused.
if value[0] & 7 != 0 || value[31] & 128 != 0 || value[31] & 64 != 1 {
if !libcrux_ecdh::validate_scalar(libcrux_ecdh::Algorithm::X25519, value).is_ok() {
Err(Error::InvalidDHSecret)
} else {
Ok(Self(Vec::from(value)))
Expand Down
2 changes: 1 addition & 1 deletion libcrux-psq/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl Session {
&self.session_key,
initiator_authenticator,
responder_ecdh_pk,
&responder_pq_pk,
responder_pq_pk,
)? != pk_binder
{
return Err(SessionError::Import);
Expand Down
Loading