Skip to content

Commit 8c62e09

Browse files
authored
RsaPssParams and RsaOaepParams fixes (#1010)
- use NULL parameters for SHA AlgorithmIdentifiers: Obviously Mozilla policy insists on having NULL parameters for MD/SHA algorithm identifiers. Change RsaPssParams/RsaOaepParams defaults to use NULL instead of empty parameters. - provide functions to construct RsaPss and RsaOaepParams: Implement RsaPssParams::new() and RsaOaepParams::new(), two functions to generate correct parameters for the provided Digest and data. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
1 parent 8c29e12 commit 8c62e09

File tree

2 files changed

+135
-23
lines changed

2 files changed

+135
-23
lines changed

pkcs1/src/params.rs

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
//! PKCS#1 RSA parameters.
22
33
use crate::{Error, Result};
4-
use der::asn1::{AnyRef, ObjectIdentifier};
54
use der::{
6-
asn1::ContextSpecificRef, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Length, Reader,
7-
Sequence, Tag, TagMode, TagNumber, Writer,
5+
asn1::{AnyRef, ContextSpecificRef, ObjectIdentifier},
6+
oid::AssociatedOid,
7+
Decode, DecodeValue, Encode, EncodeValue, FixedTag, Length, Reader, Sequence, Tag, TagMode,
8+
TagNumber, Writer,
89
};
910
use spki::{AlgorithmIdentifier, AlgorithmIdentifierRef};
1011

@@ -14,7 +15,7 @@ const OID_PSPECIFIED: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.1
1415

1516
const SHA_1_AI: AlgorithmIdentifierRef<'_> = AlgorithmIdentifierRef {
1617
oid: OID_SHA_1,
17-
parameters: None,
18+
parameters: Some(AnyRef::NULL),
1819
};
1920

2021
/// `TrailerField` as defined in [RFC 8017 Appendix 2.3].
@@ -92,6 +93,28 @@ impl<'a> RsaPssParams<'a> {
9293
/// Default RSA PSS Salt length in RsaPssParams
9394
pub const SALT_LEN_DEFAULT: u8 = 20;
9495

96+
/// Create new RsaPssParams for the provided digest and salt len
97+
pub fn new<D>(salt_len: u8) -> Self
98+
where
99+
D: AssociatedOid,
100+
{
101+
Self {
102+
hash: AlgorithmIdentifierRef {
103+
oid: D::OID,
104+
parameters: Some(AnyRef::NULL),
105+
},
106+
mask_gen: AlgorithmIdentifier {
107+
oid: OID_MGF_1,
108+
parameters: Some(AlgorithmIdentifierRef {
109+
oid: D::OID,
110+
parameters: Some(AnyRef::NULL),
111+
}),
112+
},
113+
salt_len,
114+
trailer_field: Default::default(),
115+
}
116+
}
117+
95118
fn context_specific_hash(&self) -> Option<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
96119
if self.hash == SHA_1_AI {
97120
None
@@ -238,6 +261,35 @@ pub struct RsaOaepParams<'a> {
238261
}
239262

240263
impl<'a> RsaOaepParams<'a> {
264+
/// Create new RsaPssParams for the provided digest and default (empty) label
265+
pub fn new<D>() -> Self
266+
where
267+
D: AssociatedOid,
268+
{
269+
Self::new_with_label::<D>(&[])
270+
}
271+
272+
/// Create new RsaPssParams for the provided digest and specified label
273+
pub fn new_with_label<D>(label: &'a impl AsRef<[u8]>) -> Self
274+
where
275+
D: AssociatedOid,
276+
{
277+
Self {
278+
hash: AlgorithmIdentifierRef {
279+
oid: D::OID,
280+
parameters: Some(AnyRef::NULL),
281+
},
282+
mask_gen: AlgorithmIdentifier {
283+
oid: OID_MGF_1,
284+
parameters: Some(AlgorithmIdentifierRef {
285+
oid: D::OID,
286+
parameters: Some(AnyRef::NULL),
287+
}),
288+
},
289+
p_source: pspecicied_algorithm_identifier(label),
290+
}
291+
}
292+
241293
fn context_specific_hash(&self) -> Option<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
242294
if self.hash == SHA_1_AI {
243295
None
@@ -332,12 +384,16 @@ impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> {
332384
}
333385
}
334386

335-
/// Default Source Algorithm, empty string
336-
fn default_pempty_string<'a>() -> AlgorithmIdentifierRef<'a> {
387+
fn pspecicied_algorithm_identifier(label: &impl AsRef<[u8]>) -> AlgorithmIdentifierRef<'_> {
337388
AlgorithmIdentifierRef {
338389
oid: OID_PSPECIFIED,
339390
parameters: Some(
340-
AnyRef::new(Tag::OctetString, &[]).expect("error creating default OAEP params"),
391+
AnyRef::new(Tag::OctetString, label.as_ref()).expect("error creating OAEP params"),
341392
),
342393
}
343394
}
395+
396+
/// Default Source Algorithm, empty string
397+
fn default_pempty_string<'a>() -> AlgorithmIdentifierRef<'a> {
398+
pspecicied_algorithm_identifier(&[])
399+
}

pkcs1/tests/params.rs

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,33 @@
11
//! PKCS#1 algorithm params tests
22
33
use const_oid::db;
4-
use der::{asn1::OctetStringRef, Encode};
4+
use der::{
5+
asn1::{AnyRef, ObjectIdentifier, OctetStringRef},
6+
oid::AssociatedOid,
7+
Encode,
8+
};
59
use hex_literal::hex;
610
use pkcs1::{RsaOaepParams, RsaPssParams, TrailerField};
711

812
/// Default PSS parameters using all default values (SHA1, MGF1)
913
const RSA_PSS_PARAMETERS_DEFAULTS: &[u8] = &hex!("3000");
1014
/// Example PSS parameters using SHA256 instead of SHA1
11-
const RSA_PSS_PARAMETERS_SHA2_256: &[u8] = &hex!("3030a00d300b0609608648016503040201a11a301806092a864886f70d010108300b0609608648016503040201a203020120");
15+
const RSA_PSS_PARAMETERS_SHA2_256: &[u8] = &hex!("3034a00f300d06096086480165030402010500a11c301a06092a864886f70d010108300d06096086480165030402010500a203020120");
1216

1317
/// Default OAEP parameters using all default values (SHA1, MGF1, Empty)
1418
const RSA_OAEP_PARAMETERS_DEFAULTS: &[u8] = &hex!("3000");
15-
/// Example OAEP parameters using SHA256 instead of SHA1 and 'abc' as label
16-
const RSA_OAEP_PARAMETERS_SHA2_256: &[u8] = &hex!("303fa00d300b0609608648016503040201a11a301806092a864886f70d010108300b0609608648016503040201a212301006092a864886f70d0101090403abcdef");
19+
/// Example OAEP parameters using SHA256 instead of SHA1
20+
const RSA_OAEP_PARAMETERS_SHA2_256: &[u8] = &hex!("302fa00f300d06096086480165030402010500a11c301a06092a864886f70d010108300d06096086480165030402010500");
21+
22+
struct Sha1Mock {}
23+
impl AssociatedOid for Sha1Mock {
24+
const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26");
25+
}
26+
27+
struct Sha256Mock {}
28+
impl AssociatedOid for Sha256Mock {
29+
const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.1");
30+
}
1731

1832
#[test]
1933
fn decode_pss_param() {
@@ -23,7 +37,7 @@ fn decode_pss_param() {
2337
.hash
2438
.assert_algorithm_oid(db::rfc5912::ID_SHA_256)
2539
.is_ok());
26-
assert_eq!(param.hash.parameters, None);
40+
assert_eq!(param.hash.parameters, Some(AnyRef::NULL));
2741
assert!(param
2842
.mask_gen
2943
.assert_algorithm_oid(db::rfc5912::ID_MGF_1)
@@ -56,7 +70,7 @@ fn decode_pss_param_default() {
5670
.hash
5771
.assert_algorithm_oid(db::rfc5912::ID_SHA_1)
5872
.is_ok());
59-
assert_eq!(param.hash.parameters, None);
73+
assert_eq!(param.hash.parameters, Some(AnyRef::NULL));
6074
assert!(param
6175
.mask_gen
6276
.assert_algorithm_oid(db::rfc5912::ID_MGF_1)
@@ -67,6 +81,10 @@ fn decode_pss_param_default() {
6781
.unwrap()
6882
.assert_algorithm_oid(db::rfc5912::ID_SHA_1)
6983
.is_ok());
84+
assert_eq!(
85+
param.mask_gen.parameters.unwrap().parameters,
86+
Some(AnyRef::NULL)
87+
);
7088
assert_eq!(param.salt_len, 20);
7189
assert_eq!(param.trailer_field, TrailerField::BC);
7290
assert_eq!(param, Default::default())
@@ -81,6 +99,23 @@ fn encode_pss_param_default() {
8199
);
82100
}
83101

102+
#[test]
103+
fn new_pss_param() {
104+
let mut buf = [0_u8; 256];
105+
106+
let param = RsaPssParams::new::<Sha1Mock>(20);
107+
assert_eq!(
108+
param.encode_to_slice(&mut buf).unwrap(),
109+
RSA_PSS_PARAMETERS_DEFAULTS
110+
);
111+
112+
let param = RsaPssParams::new::<Sha256Mock>(32);
113+
assert_eq!(
114+
param.encode_to_slice(&mut buf).unwrap(),
115+
RSA_PSS_PARAMETERS_SHA2_256
116+
);
117+
}
118+
84119
#[test]
85120
fn decode_oaep_param() {
86121
let param = RsaOaepParams::try_from(RSA_OAEP_PARAMETERS_SHA2_256).unwrap();
@@ -89,7 +124,7 @@ fn decode_oaep_param() {
89124
.hash
90125
.assert_algorithm_oid(db::rfc5912::ID_SHA_256)
91126
.is_ok());
92-
assert_eq!(param.hash.parameters, None);
127+
assert_eq!(param.hash.parameters, Some(AnyRef::NULL));
93128
assert!(param
94129
.mask_gen
95130
.assert_algorithm_oid(db::rfc5912::ID_MGF_1)
@@ -104,14 +139,13 @@ fn decode_oaep_param() {
104139
.p_source
105140
.assert_algorithm_oid(db::rfc5912::ID_P_SPECIFIED)
106141
.is_ok());
107-
assert_eq!(
108-
param
109-
.p_source
110-
.parameters_any()
111-
.unwrap()
112-
.decode_as::<OctetStringRef<'_>>(),
113-
OctetStringRef::new(&[0xab, 0xcd, 0xef])
114-
);
142+
assert!(param
143+
.p_source
144+
.parameters_any()
145+
.unwrap()
146+
.decode_as::<OctetStringRef<'_>>()
147+
.unwrap()
148+
.is_empty(),);
115149
}
116150

117151
#[test]
@@ -132,7 +166,7 @@ fn decode_oaep_param_default() {
132166
.hash
133167
.assert_algorithm_oid(db::rfc5912::ID_SHA_1)
134168
.is_ok());
135-
assert_eq!(param.hash.parameters, None);
169+
assert_eq!(param.hash.parameters, Some(AnyRef::NULL));
136170
assert!(param
137171
.mask_gen
138172
.assert_algorithm_oid(db::rfc5912::ID_MGF_1)
@@ -143,6 +177,10 @@ fn decode_oaep_param_default() {
143177
.unwrap()
144178
.assert_algorithm_oid(db::rfc5912::ID_SHA_1)
145179
.is_ok());
180+
assert_eq!(
181+
param.mask_gen.parameters.unwrap().parameters,
182+
Some(AnyRef::NULL)
183+
);
146184
assert!(param
147185
.p_source
148186
.assert_algorithm_oid(db::rfc5912::ID_P_SPECIFIED)
@@ -165,3 +203,21 @@ fn encode_oaep_param_default() {
165203
RSA_OAEP_PARAMETERS_DEFAULTS
166204
);
167205
}
206+
207+
#[test]
208+
fn new_oaep_param() {
209+
let mut buf = [0_u8; 256];
210+
211+
let param = RsaOaepParams::new::<Sha1Mock>();
212+
assert_eq!(
213+
param.encode_to_slice(&mut buf).unwrap(),
214+
RSA_OAEP_PARAMETERS_DEFAULTS
215+
);
216+
217+
let param = RsaOaepParams::new::<Sha256Mock>();
218+
println!("{:02x?}", param.encode_to_slice(&mut buf).unwrap());
219+
assert_eq!(
220+
param.encode_to_slice(&mut buf).unwrap(),
221+
RSA_OAEP_PARAMETERS_SHA2_256
222+
);
223+
}

0 commit comments

Comments
 (0)