@@ -17,6 +17,7 @@ use crate::hash::Type as MdType;
17
17
use crate :: private:: UnsafeFrom ;
18
18
use crate :: rng:: Random ;
19
19
use core:: convert:: TryInto ;
20
+ use core:: ops:: Sub ;
20
21
use core:: ptr;
21
22
22
23
use byteorder:: { BigEndian , ByteOrder } ;
@@ -691,6 +692,13 @@ impl Pk {
691
692
return Err ( Error :: RsaOutputTooLarge ) ;
692
693
}
693
694
695
+ // Don't process outside of {2, ..., n-2}
696
+ let nm1 = self . rsa_public_modulus ( ) ?. sub ( & Mpi :: new ( 1 ) ?) ?;
697
+ let c_mpi = Mpi :: from_binary ( cipher) ?;
698
+ if c_mpi <= Mpi :: new ( 1 ) . unwrap ( ) || c_mpi >= nm1 {
699
+ return Err ( Error :: MpiBadInputData ) ;
700
+ }
701
+
694
702
unsafe {
695
703
rsa_private ( ctx, Some ( F :: call) , rng. data_ptr ( ) , cipher. as_ptr ( ) , plain. as_mut_ptr ( ) ) . into_result ( ) ?;
696
704
} ;
@@ -1023,6 +1031,7 @@ mod tests {
1023
1031
use super :: * ;
1024
1032
use crate :: hash:: { MdInfo , Type } ;
1025
1033
use crate :: pk:: Type as PkType ;
1034
+ use core:: ops:: Sub ;
1026
1035
1027
1036
// This is test data that must match library output *exactly*
1028
1037
const TEST_PEM : & ' static str = "-----BEGIN RSA PRIVATE KEY-----
@@ -1470,4 +1479,38 @@ iy6KC991zzvaWY/Ys+q/84Afqa+0qJKQnPuy/7F5GkVdQA/lfbhi
1470
1479
assert ! ( pk. custom_public_key( ) . is_err( ) ) ;
1471
1480
assert ! ( pk. custom_private_key( ) . is_err( ) ) ;
1472
1481
}
1482
+
1483
+ #[ test]
1484
+ fn fips_rsadp_bounds ( ) {
1485
+ let rng = & mut crate :: test_support:: rand:: test_rng ( ) ;
1486
+ let ( bitlen, exp) = ( 2048 , 0x10001 ) ;
1487
+ let mut pk = Pk :: generate_rsa ( rng, bitlen, exp) . unwrap ( ) ;
1488
+ pk. set_options ( Options :: Rsa {
1489
+ padding : RsaPadding :: None ,
1490
+ } ) ;
1491
+
1492
+ const LEN : usize = 256 ;
1493
+
1494
+ // Decrypting anything out of {2, n-2} should fail
1495
+ let expected_err = Error :: MpiBadInputData ;
1496
+
1497
+ let mut pt = [ 0x00 ; LEN ] ;
1498
+
1499
+ let _0 = Mpi :: new ( 0 ) . unwrap ( ) ;
1500
+ let _1 = Mpi :: new ( 1 ) . unwrap ( ) ;
1501
+ let _2 = Mpi :: new ( 2 ) . unwrap ( ) ;
1502
+ let n = pk. rsa_public_modulus ( ) . unwrap ( ) ;
1503
+ let nm1 = pk. rsa_public_modulus ( ) . unwrap ( ) . sub ( & Mpi :: new ( 1 ) . unwrap ( ) ) . unwrap ( ) ;
1504
+ let nm2 = pk. rsa_public_modulus ( ) . unwrap ( ) . sub ( & Mpi :: new ( 2 ) . unwrap ( ) ) . unwrap ( ) ;
1505
+ for c in [ _0, _1, nm1, n] {
1506
+ let ct = c. to_binary_padded ( LEN ) . unwrap ( ) ;
1507
+ let l = pk. decrypt ( & ct, & mut pt, rng) ;
1508
+ assert_eq ! ( l. unwrap_err( ) , expected_err) ;
1509
+ }
1510
+ for c in [ _2, nm2] {
1511
+ let ct = c. to_binary_padded ( LEN ) . unwrap ( ) ;
1512
+ let l = pk. decrypt ( & ct, & mut pt, rng) ;
1513
+ assert_eq ! ( l. unwrap( ) , LEN ) ;
1514
+ }
1515
+ }
1473
1516
}
0 commit comments