Skip to content

Commit 759f236

Browse files
committed
Reject PSS salt lengths that do not fit in a u8
`get_pss_signature_algo_id` cast the salt length to `u8` with `as`, silently truncating any value >= 256 (e.g. 256 -> 0). The resulting RSASSA-PSS `AlgorithmIdentifier` then advertised the wrong salt length, so signatures produced with such a salt length failed verification. Take the salt length as `usize` in the helper and convert it with `u8::try_from`, returning a DER `Overflow` error when it does not fit, rather than encoding an incorrect value. Both `SigningKey` and `BlindedSigningKey` funnel through this helper, so both signing paths are covered. Fixes #703.
1 parent 4a6006f commit 759f236

3 files changed

Lines changed: 30 additions & 6 deletions

File tree

src/pss.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ use {
3939
crate::encoding::ID_RSASSA_PSS,
4040
const_oid::AssociatedOid,
4141
pkcs1::RsaPssParams,
42-
spki::{der::Any, AlgorithmIdentifierOwned},
42+
spki::{
43+
der::{Any, ErrorKind},
44+
AlgorithmIdentifierOwned,
45+
},
4346
};
4447

4548
/// Digital signatures using PSS padding.
@@ -272,15 +275,16 @@ pub fn get_default_pss_signature_algo_id<D>() -> spki::Result<AlgorithmIdentifie
272275
where
273276
D: Digest + AssociatedOid,
274277
{
275-
let salt_len: u8 = <D as Digest>::output_size() as u8;
276-
get_pss_signature_algo_id::<D>(salt_len)
278+
get_pss_signature_algo_id::<D>(<D as Digest>::output_size())
277279
}
278280

279281
#[cfg(feature = "encoding")]
280-
fn get_pss_signature_algo_id<D>(salt_len: u8) -> spki::Result<AlgorithmIdentifierOwned>
282+
fn get_pss_signature_algo_id<D>(salt_len: usize) -> spki::Result<AlgorithmIdentifierOwned>
281283
where
282284
D: Digest + AssociatedOid,
283285
{
286+
// RsaPssParams encodes salt_len in a single byte; reject rather than truncate.
287+
let salt_len = u8::try_from(salt_len).map_err(|_| ErrorKind::Overflow.to_error())?;
284288
let pss_params = RsaPssParams::new::<D>(salt_len);
285289

286290
Ok(AlgorithmIdentifierOwned {
@@ -672,4 +676,24 @@ tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
672676
.expect("verification to succeed");
673677
}
674678
}
679+
680+
// A salt length that does not fit in a byte must be rejected, not truncated (#703).
681+
#[test]
682+
fn signature_algorithm_identifier_rejects_oversized_salt_len() {
683+
use spki::DynSignatureAlgorithmIdentifier;
684+
685+
let priv_key = get_private_key();
686+
687+
// largest value that fits in a byte
688+
let ok_key = SigningKey::<Sha1>::new_with_salt_len(priv_key.clone(), 255);
689+
assert!(ok_key.signature_algorithm_identifier().is_ok());
690+
691+
// would wrap to 0
692+
let bad_key = SigningKey::<Sha1>::new_with_salt_len(priv_key.clone(), 256);
693+
assert!(bad_key.signature_algorithm_identifier().is_err());
694+
695+
// blinded key uses the same path
696+
let bad_blinded = BlindedSigningKey::<Sha1>::new_with_salt_len(priv_key, 256);
697+
assert!(bad_blinded.signature_algorithm_identifier().is_err());
698+
}
675699
}

src/pss/blinded_signing_key.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ where
184184
D: Digest + AssociatedOid,
185185
{
186186
fn signature_algorithm_identifier(&self) -> spki::Result<AlgorithmIdentifierOwned> {
187-
get_pss_signature_algo_id::<D>(self.salt_len as u8)
187+
get_pss_signature_algo_id::<D>(self.salt_len)
188188
}
189189
}
190190

src/pss/signing_key.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ where
221221
D: Digest + AssociatedOid,
222222
{
223223
fn signature_algorithm_identifier(&self) -> spki::Result<AlgorithmIdentifierOwned> {
224-
get_pss_signature_algo_id::<D>(self.salt_len as u8)
224+
get_pss_signature_algo_id::<D>(self.salt_len)
225225
}
226226
}
227227

0 commit comments

Comments
 (0)