Skip to content

Commit f6df3e2

Browse files
authored
dsa: add from_components_unchecked APIs (#1059)
Adds support for any size of keys, either larger or older/weak keys. The API is only available under the `hazmat` feature-flag, and the consumer is responsible for checking the security of what they're using it for. Fixes #1058 * dsa: compare key sizes aligned to limb This allows to compare key sizes after a back and forth through serialization which could lose the exact key size.
1 parent 51dd7d8 commit f6df3e2

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
lines changed

dsa/src/components.rs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,44 @@ pub struct Components {
3131
impl Components {
3232
/// Construct the common components container from its inner values (p, q and g)
3333
pub fn from_components(p: BoxedUint, q: BoxedUint, g: BoxedUint) -> signature::Result<Self> {
34+
let (p, q, g) = Self::adapt_components(p, q, g)?;
35+
36+
let key_size = match (p.bits_precision(), q.bits_precision()) {
37+
#[allow(deprecated)]
38+
(p, q) if KeySize::DSA_1024_160.matches(p, q) => KeySize::DSA_1024_160,
39+
(p, q) if KeySize::DSA_2048_224.matches(p, q) => KeySize::DSA_2048_224,
40+
(p, q) if KeySize::DSA_2048_256.matches(p, q) => KeySize::DSA_2048_256,
41+
(p, q) if KeySize::DSA_3072_256.matches(p, q) => KeySize::DSA_3072_256,
42+
_ => return Err(signature::Error::new()),
43+
};
44+
45+
Ok(Self { p, q, g, key_size })
46+
}
47+
48+
/// Construct the common components container from its inner values (p, q and g)
49+
///
50+
/// # Safety
51+
///
52+
/// Any length of keys may be used, no checks are to be performed. You are responsible for
53+
/// checking the key strengths.
54+
#[cfg(feature = "hazmat")]
55+
pub fn from_components_unchecked(
56+
p: BoxedUint,
57+
q: BoxedUint,
58+
g: BoxedUint,
59+
) -> signature::Result<Self> {
60+
let (p, q, g) = Self::adapt_components(p, q, g)?;
61+
let key_size = KeySize::other(p.bits_precision(), q.bits_precision());
62+
63+
Ok(Self { p, q, g, key_size })
64+
}
65+
66+
/// Helper method to build a [`Components`]
67+
fn adapt_components(
68+
p: BoxedUint,
69+
q: BoxedUint,
70+
g: BoxedUint,
71+
) -> signature::Result<(Odd<BoxedUint>, NonZero<BoxedUint>, NonZero<BoxedUint>)> {
3472
let p = Odd::new(p)
3573
.into_option()
3674
.ok_or_else(signature::Error::new)?;
@@ -45,16 +83,7 @@ impl Components {
4583
return Err(signature::Error::new());
4684
}
4785

48-
let key_size = match (p.bits_precision(), q.bits_precision()) {
49-
#[allow(deprecated)]
50-
(p, q) if KeySize::DSA_1024_160.matches(p, q) => KeySize::DSA_1024_160,
51-
(p, q) if KeySize::DSA_2048_224.matches(p, q) => KeySize::DSA_2048_224,
52-
(p, q) if KeySize::DSA_2048_256.matches(p, q) => KeySize::DSA_2048_256,
53-
(p, q) if KeySize::DSA_3072_256.matches(p, q) => KeySize::DSA_3072_256,
54-
_ => return Err(signature::Error::new()),
55-
};
56-
57-
Ok(Self { p, q, g, key_size })
86+
Ok((p, q, g))
5887
}
5988

6089
/// Generate a new pair of common components

dsa/src/size.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use core::cmp::Ordering;
12
use crypto_bigint::Limb;
23

34
/// DSA key size
4-
#[derive(Clone, Debug, Copy, PartialEq, PartialOrd)]
5+
#[derive(Clone, Debug, Copy)]
56
pub struct KeySize {
67
/// Bit size of p
78
pub(crate) l: u32,
@@ -25,6 +26,14 @@ impl KeySize {
2526

2627
/// DSA parameter size constant: L = 3072, N = 256
2728
pub const DSA_3072_256: Self = Self { l: 3072, n: 256 };
29+
30+
/// Create a KeySize from other, potentially unsafe, key lengths
31+
///
32+
/// This aims at supporting non-standard or older/weak keys.
33+
#[cfg(feature = "hazmat")]
34+
pub(crate) fn other(l: u32, n: u32) -> Self {
35+
Self { l, n }
36+
}
2837
}
2938

3039
impl KeySize {
@@ -40,3 +49,18 @@ impl KeySize {
4049
l == self.l_aligned() && n == self.n_aligned()
4150
}
4251
}
52+
53+
impl PartialEq for KeySize {
54+
fn eq(&self, other: &Self) -> bool {
55+
self.l_aligned() == other.l_aligned() && self.n_aligned() == other.n_aligned()
56+
}
57+
}
58+
59+
impl PartialOrd for KeySize {
60+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
61+
let l = self.l_aligned().partial_cmp(&other.l_aligned())?;
62+
let n = self.n_aligned().partial_cmp(&other.n_aligned())?;
63+
64+
Some(l.then(n))
65+
}
66+
}

0 commit comments

Comments
 (0)