Skip to content

Commit a09022c

Browse files
Merge pull request #1301 from cryspen/jonas/psq-fix-clamp-check
[PSQ] Fix broken clamping check
2 parents 784ddd7 + 006156e commit a09022c

7 files changed

Lines changed: 27 additions & 4 deletions

File tree

crates/algorithms/curve25519/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
- [#1301](https://github.com/cryspen/libcrux/pull/1301): Expose scalar clamping and provide check for clamped-ness
11+
812
## [0.0.5] (2026-01-22)
913

1014
- [#1297](https://github.com/cryspen/libcrux/pull/1297): Update dependencies

crates/algorithms/curve25519/src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,18 @@ impl libcrux_traits::kem::arrayref::Kem<DK_LEN, EK_LEN, EK_LEN, SS_LEN, DK_LEN,
7474
libcrux_traits::kem::slice::impl_trait!(X25519 => EK_LEN, DK_LEN, EK_LEN, EK_LEN, DK_LEN, DK_LEN);
7575

7676
/// Clamp a scalar.
77-
fn clamp(scalar: &mut [u8; DK_LEN]) {
77+
pub fn clamp(scalar: &mut [u8; DK_LEN]) {
7878
// We clamp the key already to make sure it can't be misused.
7979
scalar[0] &= 248u8;
8080
scalar[31] &= 127u8;
8181
scalar[31] |= 64u8;
8282
}
83+
84+
/// Test whether a scalar is already clamped, error indicating that it is not.
85+
pub fn is_clamped(scalar: &[u8; DK_LEN]) -> Result<(), Error> {
86+
if scalar[0] & 7 != 0 || scalar[31] & 128 != 0 || scalar[31] & 64 != 64 {
87+
Err(Error)
88+
} else {
89+
Ok(())
90+
}
91+
}

libcrux-ecdh/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
- [#1301](https://github.com/cryspen/libcrux/pull/1301): Check length and clamping in X25519 secret validation
11+
812
## [0.0.5] (2026-01-22)
913

1014
- [#1297](https://github.com/cryspen/libcrux/pull/1297): Update dependencies

libcrux-ecdh/src/ecdh.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,12 @@ pub fn secret_to_public(alg: Algorithm, scalar: impl AsRef<[u8]>) -> Result<Vec<
125125
pub fn validate_scalar(alg: Algorithm, s: impl AsRef<[u8]>) -> Result<(), Error> {
126126
match alg {
127127
Algorithm::X25519 => {
128-
if s.as_ref().iter().all(|&b| b == 0) {
128+
if s.as_ref().iter().all(|&b| b == 0)
129+
|| libcrux_curve25519::is_clamped(
130+
s.as_ref().try_into().map_err(|_| Error::InvalidScalar)?,
131+
)
132+
.is_err()
133+
{
129134
Err(Error::InvalidScalar)
130135
} else {
131136
Ok(())

libcrux-psq/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

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

libcrux-psq/src/handshake/dhkem.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl DHPrivateKey {
9797
/// Import a Diffie-Hellman private key from raw bytes.
9898
pub fn from_bytes(value: &[u8; 32]) -> Result<Self, Error> {
9999
// Test whether the key is already clamped to make sure it can't be misused.
100-
if value[0] & 7 != 0 || value[31] & 128 != 0 || value[31] & 64 != 1 {
100+
if !libcrux_ecdh::validate_scalar(libcrux_ecdh::Algorithm::X25519, value).is_ok() {
101101
Err(Error::InvalidDHSecret)
102102
} else {
103103
Ok(Self(Vec::from(value)))

libcrux-psq/src/session.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ impl Session {
291291
&self.session_key,
292292
initiator_authenticator,
293293
responder_ecdh_pk,
294-
&responder_pq_pk,
294+
responder_pq_pk,
295295
)? != pk_binder
296296
{
297297
return Err(SessionError::Import);

0 commit comments

Comments
 (0)