@@ -36,8 +36,11 @@ pub static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgori
3636 RSA_PSS_SHA384 ,
3737 RSA_PSS_SHA256 ,
3838 RSA_PKCS1_SHA512 ,
39+ RSA_PKCS1_SHA512_ABSENT_PARAMS ,
3940 RSA_PKCS1_SHA384 ,
41+ RSA_PKCS1_SHA384_ABSENT_PARAMS ,
4042 RSA_PKCS1_SHA256 ,
43+ RSA_PKCS1_SHA256_ABSENT_PARAMS ,
4144 ] ,
4245 mapping : & [
4346 //Note: for TLS1.2 the curve is not fixed by SignatureScheme. For TLS1.3 it is.
@@ -69,6 +72,18 @@ pub(crate) static RSA_PKCS1_SHA256: &dyn SignatureVerificationAlgorithm = &Verif
6972 params : Params :: Rsa ( RsaPadding :: PKCS1 ) ,
7073} ;
7174
75+ /// RSA PKCS#1 1.5 signatures using SHA-256 with absent AlgorithmIdentifier parameters.
76+ pub ( crate ) static RSA_PKCS1_SHA256_ABSENT_PARAMS : & dyn SignatureVerificationAlgorithm =
77+ & VerificationAlgorithm {
78+ display_name : "RSA_PKCS1_SHA256_ABSENT_PARAMS" ,
79+ public_key_alg_id : alg_id:: RSA_ENCRYPTION ,
80+ signature_alg_id : AlgorithmIdentifier :: from_slice ( & [
81+ 0x30 , 0x0b , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x0b ,
82+ ] ) ,
83+ hash : SHA256 ,
84+ params : Params :: Rsa ( RsaPadding :: PKCS1 ) ,
85+ } ;
86+
7287/// RSA PKCS#1 1.5 signatures using SHA-384.
7388pub ( crate ) static RSA_PKCS1_SHA384 : & dyn SignatureVerificationAlgorithm = & VerificationAlgorithm {
7489 display_name : "RSA_PKCS1_SHA384" ,
@@ -78,6 +93,18 @@ pub(crate) static RSA_PKCS1_SHA384: &dyn SignatureVerificationAlgorithm = &Verif
7893 params : Params :: Rsa ( RsaPadding :: PKCS1 ) ,
7994} ;
8095
96+ /// RSA PKCS#1 1.5 signatures using SHA-384 with absent AlgorithmIdentifier parameters.
97+ pub ( crate ) static RSA_PKCS1_SHA384_ABSENT_PARAMS : & dyn SignatureVerificationAlgorithm =
98+ & VerificationAlgorithm {
99+ display_name : "RSA_PKCS1_SHA384_ABSENT_PARAMS" ,
100+ public_key_alg_id : alg_id:: RSA_ENCRYPTION ,
101+ signature_alg_id : AlgorithmIdentifier :: from_slice ( & [
102+ 0x30 , 0x0b , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x0c ,
103+ ] ) ,
104+ hash : SHA384 ,
105+ params : Params :: Rsa ( RsaPadding :: PKCS1 ) ,
106+ } ;
107+
81108/// RSA PKCS#1 1.5 signatures using SHA-512.
82109pub ( crate ) static RSA_PKCS1_SHA512 : & dyn SignatureVerificationAlgorithm = & VerificationAlgorithm {
83110 display_name : "RSA_PKCS1_SHA512" ,
@@ -87,6 +114,18 @@ pub(crate) static RSA_PKCS1_SHA512: &dyn SignatureVerificationAlgorithm = &Verif
87114 params : Params :: Rsa ( RsaPadding :: PKCS1 ) ,
88115} ;
89116
117+ /// RSA PKCS#1 1.5 signatures using SHA-512 with absent AlgorithmIdentifier parameters.
118+ pub ( crate ) static RSA_PKCS1_SHA512_ABSENT_PARAMS : & dyn SignatureVerificationAlgorithm =
119+ & VerificationAlgorithm {
120+ display_name : "RSA_PKCS1_SHA512_ABSENT_PARAMS" ,
121+ public_key_alg_id : alg_id:: RSA_ENCRYPTION ,
122+ signature_alg_id : AlgorithmIdentifier :: from_slice ( & [
123+ 0x30 , 0x0b , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x0d ,
124+ ] ) ,
125+ hash : SHA512 ,
126+ params : Params :: Rsa ( RsaPadding :: PKCS1 ) ,
127+ } ;
128+
90129/// RSA PSS signatures using SHA-256.
91130pub ( crate ) static RSA_PSS_SHA256 : & dyn SignatureVerificationAlgorithm = & VerificationAlgorithm {
92131 display_name : "RSA_PSS_SHA256" ,
@@ -210,6 +249,22 @@ enum Params {
210249unsafe impl Send for Params { }
211250unsafe impl Sync for Params { }
212251
252+ const RSA_MIN_MODULUS_BITS : usize = 2048 ;
253+ const RSA_MAX_MODULUS_BITS : usize = 8192 ;
254+
255+ fn rsa_public_key_allowed_by_webpki ( key : & RsaPublicKey < ' _ > ) -> bool {
256+ ( RSA_MIN_MODULUS_BITS ..=RSA_MAX_MODULUS_BITS )
257+ . contains ( & rsa_modulus_bit_len ( key. modulus . as_bytes ( ) ) )
258+ }
259+
260+ fn rsa_modulus_bit_len ( modulus : & [ u8 ] ) -> usize {
261+ let Some ( first) = modulus. first ( ) else {
262+ return 0 ;
263+ } ;
264+
265+ ( modulus. len ( ) - 1 ) * 8 + ( u8:: BITS as usize - first. leading_zeros ( ) as usize )
266+ }
267+
213268#[ derive( Debug ) ]
214269enum RsaPadding {
215270 PKCS1 ,
@@ -236,6 +291,9 @@ impl<const HASH_SIZE: usize> SignatureVerificationAlgorithm for VerificationAlgo
236291 match & self . params {
237292 Params :: Rsa ( padding) => {
238293 let key = RsaPublicKey :: try_from ( public_key) . map_err ( |_| InvalidSignature ) ?;
294+ if !rsa_public_key_allowed_by_webpki ( & key) {
295+ return Err ( InvalidSignature ) ;
296+ }
239297 let handle = import_rsa_public_key ( & key) . map_err ( |_| InvalidSignature ) ?;
240298
241299 match padding {
@@ -269,10 +327,7 @@ impl<const HASH_SIZE: usize> SignatureVerificationAlgorithm for VerificationAlgo
269327 BCRYPT_PAD_PSS ,
270328 )
271329 . ok ( )
272- . map_err ( |e| {
273- dbg ! ( e) ;
274- InvalidSignature
275- } )
330+ . map_err ( |_| InvalidSignature )
276331 }
277332 }
278333 }
@@ -343,6 +398,88 @@ mod tests {
343398 use super :: * ;
344399 use wycheproof:: TestResult ;
345400
401+ const RSA_PKCS1_SHA256_ABSENT_PARAMS_DER : & [ u8 ] = & [
402+ 0x30 , 0x0b , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x0b ,
403+ ] ;
404+ const RSA_PKCS1_SHA384_ABSENT_PARAMS_DER : & [ u8 ] = & [
405+ 0x30 , 0x0b , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x0c ,
406+ ] ;
407+ const RSA_PKCS1_SHA512_ABSENT_PARAMS_DER : & [ u8 ] = & [
408+ 0x30 , 0x0b , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x0d ,
409+ ] ;
410+
411+ #[ test]
412+ fn supported_algorithms_include_rsa_pkcs1_absent_parameter_variants ( ) {
413+ for signature_alg_id in [
414+ AlgorithmIdentifier :: from_slice ( RSA_PKCS1_SHA256_ABSENT_PARAMS_DER ) ,
415+ AlgorithmIdentifier :: from_slice ( RSA_PKCS1_SHA384_ABSENT_PARAMS_DER ) ,
416+ AlgorithmIdentifier :: from_slice ( RSA_PKCS1_SHA512_ABSENT_PARAMS_DER ) ,
417+ ] {
418+ assert ! ( SUPPORTED_SIG_ALGS
419+ . all
420+ . iter( )
421+ . any( |alg| alg. signature_alg_id( ) == signature_alg_id) ) ;
422+ }
423+ }
424+
425+ #[ test]
426+ fn rsa_public_key_policy_matches_webpki_2048_to_8192_bit_bounds ( ) {
427+ let key_2047 = rsa_public_key_with_modulus ( & modulus_with_bit_len ( 2047 ) ) ;
428+ let key_2048 = rsa_public_key_with_modulus ( & modulus_with_bit_len ( 2048 ) ) ;
429+ let key_8192 = rsa_public_key_with_modulus ( & modulus_with_bit_len ( 8192 ) ) ;
430+ let key_8193 = rsa_public_key_with_modulus ( & modulus_with_bit_len ( 8193 ) ) ;
431+
432+ assert ! ( !rsa_public_key_allowed_by_webpki( & key_2047) ) ;
433+ assert ! ( rsa_public_key_allowed_by_webpki( & key_2048) ) ;
434+ assert ! ( rsa_public_key_allowed_by_webpki( & key_8192) ) ;
435+ assert ! ( !rsa_public_key_allowed_by_webpki( & key_8193) ) ;
436+ }
437+
438+ fn rsa_public_key_with_modulus ( modulus : & [ u8 ] ) -> RsaPublicKey < ' static > {
439+ let mut der = Vec :: new ( ) ;
440+ append_der_integer ( & mut der, modulus) ;
441+ append_der_integer ( & mut der, & [ 0x01 , 0x00 , 0x01 ] ) ;
442+
443+ let mut sequence = Vec :: new ( ) ;
444+ sequence. push ( 0x30 ) ;
445+ append_der_len ( & mut sequence, der. len ( ) ) ;
446+ sequence. extend_from_slice ( & der) ;
447+
448+ RsaPublicKey :: try_from ( Box :: leak ( sequence. into_boxed_slice ( ) ) . as_ref ( ) ) . unwrap ( )
449+ }
450+
451+ fn modulus_with_bit_len ( bit_len : usize ) -> Vec < u8 > {
452+ let len = bit_len. div_ceil ( 8 ) ;
453+ let mut modulus = vec ! [ 0xff ; len] ;
454+ modulus[ 0 ] = 1 << ( ( bit_len - 1 ) % 8 ) ;
455+ modulus
456+ }
457+
458+ fn append_der_integer ( der : & mut Vec < u8 > , value : & [ u8 ] ) {
459+ der. push ( 0x02 ) ;
460+ let needs_leading_zero = value. first ( ) . is_some_and ( |byte| byte & 0x80 != 0 ) ;
461+ append_der_len ( der, value. len ( ) + usize:: from ( needs_leading_zero) ) ;
462+ if needs_leading_zero {
463+ der. push ( 0 ) ;
464+ }
465+ der. extend_from_slice ( value) ;
466+ }
467+
468+ fn append_der_len ( der : & mut Vec < u8 > , len : usize ) {
469+ if len < 128 {
470+ der. push ( len as u8 ) ;
471+ return ;
472+ }
473+
474+ let len_bytes = len. to_be_bytes ( ) ;
475+ let first = len_bytes
476+ . iter ( )
477+ . position ( |byte| * byte != 0 )
478+ . unwrap_or ( len_bytes. len ( ) - 1 ) ;
479+ der. push ( 0x80 | ( len_bytes. len ( ) - first) as u8 ) ;
480+ der. extend_from_slice ( & len_bytes[ first..] ) ;
481+ }
482+
346483 #[ test]
347484 fn test_open_ssl_algorithm_debug ( ) {
348485 assert_eq ! (
0 commit comments