@@ -95,15 +95,15 @@ impl Certificate {
9595 pub fn from_pem ( pem : & [ u8 ] ) -> Result < MbedtlsBox < Certificate > > {
9696 let mut cert = MbedtlsBox :: < Certificate > :: init ( ) ?;
9797 unsafe { x509_crt_parse ( ( & mut ( * cert) ) . into ( ) , pem. as_ptr ( ) , pem. len ( ) ) } . into_result ( ) ?;
98-
98+
9999 if !( * cert) . inner . next . is_null ( ) {
100100 // Use from_pem_multiple for parsing multiple certificates in a pem.
101101 return Err ( codes:: X509BadInputData . into ( ) ) ;
102102 }
103103
104104 Ok ( cert)
105105 }
106-
106+
107107 /// Input must be NULL-terminated
108108 pub fn from_pem_multiple ( pem : & [ u8 ] ) -> Result < MbedtlsList < Certificate > > {
109109 let mut cert = MbedtlsBox :: < Certificate > :: init ( ) ?;
@@ -113,7 +113,7 @@ impl Certificate {
113113 list. push ( cert) ;
114114 Ok ( list)
115115 }
116-
116+
117117 pub fn check_key_usage ( & self , usage : super :: KeyUsage ) -> bool {
118118 unsafe { x509_crt_check_key_usage ( & self . inner , usage. bits ( ) ) }
119119 . into_result ( )
@@ -233,6 +233,9 @@ impl Certificate {
233233 where
234234 F : VerifyCallback + ' static ,
235235 {
236+ if chain. is_empty ( ) {
237+ return Err ( codes:: X509BadInputData . into ( ) ) ;
238+ }
236239 let ( f_vrfy, p_vrfy) : ( Option < unsafe extern "C" fn ( _, _, _, _) -> _ > , _ ) = if let Some ( cb) = cb. as_ref ( ) {
237240 ( Some ( x509:: verify_callback :: < F > ) ,
238241 cb as * const _ as * mut c_void )
@@ -509,11 +512,11 @@ impl MbedtlsBox<Certificate> {
509512
510513 let inner = NonNull :: new ( inner) . ok_or ( codes:: X509AllocFailed ) ?;
511514 x509_crt_init ( inner. as_ptr ( ) ) ;
512-
515+
513516 Ok ( MbedtlsBox { inner : inner. cast ( ) } )
514517 }
515518 }
516-
519+
517520 fn list_next ( & self ) -> Option < & MbedtlsBox < Certificate > > {
518521 unsafe {
519522 <& Option < MbedtlsBox < _ > > as UnsafeFrom < _ > >:: from ( & ( * * self ) . inner . next ) . unwrap ( ) . as_ref ( )
@@ -566,11 +569,11 @@ impl MbedtlsList<Certificate> {
566569 // This leaks a *mut Certificate that we can cast to x509_crt as it's transparent and has no extra fields.
567570 self . inner . take ( ) . map ( |x| x. into_raw ( ) ) . unwrap_or ( core:: ptr:: null_mut ( ) ) as * mut x509_crt
568571 }
569-
572+
570573 pub fn is_empty ( & self ) -> bool {
571574 self . inner . is_none ( )
572575 }
573-
576+
574577 pub fn push ( & mut self , certificate : MbedtlsBox < Certificate > ) -> ( ) {
575578 self . append ( MbedtlsList :: < Certificate > { inner : Some ( certificate) } ) ;
576579 }
@@ -585,12 +588,12 @@ impl MbedtlsList<Certificate> {
585588 }
586589 prev = cur;
587590 }
588-
591+
589592 // no iterations in for loop: head equals tail
590593 self . inner . take ( )
591594 }
592595
593-
596+
594597 pub fn pop_front ( & mut self ) -> Option < MbedtlsBox < Certificate > > {
595598 let mut ret = self . inner . take ( ) ?;
596599 self . inner = ret. list_next_mut ( ) . take ( ) ;
@@ -605,7 +608,7 @@ impl MbedtlsList<Certificate> {
605608 } ;
606609 * tail = list. inner ;
607610 }
608-
611+
609612 pub fn iter ( & self ) -> Iter < ' _ > {
610613 Iter { next : self . inner . as_ref ( ) }
611614 }
@@ -874,7 +877,7 @@ JS7pkcufTIoN0Yj0SxAWLW711FgB
874877 assert_eq ! ( output, TEST_PEM ) ;
875878 }
876879
877-
880+
878881 const TEST_CERT_PEM : & ' static str = "-----BEGIN CERTIFICATE-----
879882MIIDLDCCAhSgAwIBAgIRALY0SS5pY9Yb/aIHvSAvmOswDQYJKoZIhvcNAQELBQAw
880883HzEQMA4GA1UEAxMHVGVzdCBDQTELMAkGA1UEBhMCVVMwHhcNMTkwMTA4MDAxODM1
@@ -898,7 +901,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
898901 #[ test]
899902 fn cert_field_access ( ) {
900903 let cert = Certificate :: from_pem ( TEST_CERT_PEM . as_bytes ( ) ) . unwrap ( ) ;
901-
904+
902905 assert_eq ! ( cert. version( ) . unwrap( ) , CertificateVersion :: V3 ) ;
903906 assert_eq ! ( cert. issuer( ) . unwrap( ) , "CN=Test CA, C=US" ) ;
904907 assert_eq ! ( cert. subject( ) . unwrap( ) , "CN=Test Cert, O=Test" ) ;
@@ -975,7 +978,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
975978
976979 let mut iter = list. iter ( ) ;
977980 let cert = iter. next ( ) . unwrap ( ) ;
978-
981+
979982 let pk = cert. public_key ( ) ;
980983
981984 assert_eq ! ( pk. pk_type( ) , crate :: pk:: Type :: Rsa ) ;
@@ -1011,7 +1014,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
10111014 let c_int1 = Certificate :: from_pem ( C_INT1 . as_bytes ( ) ) . unwrap ( ) ;
10121015 let c_int2 = Certificate :: from_pem ( C_INT2 . as_bytes ( ) ) . unwrap ( ) ;
10131016 let mut c_root = Certificate :: from_pem_multiple ( C_ROOT . as_bytes ( ) ) . unwrap ( ) ;
1014-
1017+
10151018 // Certificate C_INT2 is missing at the beginning so the verification should fail at first
10161019 let mut chain = MbedtlsList :: < Certificate > :: new ( ) ;
10171020 chain. push ( c_leaf. clone ( ) ) ;
@@ -1041,7 +1044,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
10411044 Err ( e) => panic ! ( "Failed to verify, error: {}, err_str: {}" , e, err_str) ,
10421045 } ;
10431046 }
1044-
1047+
10451048 #[ test]
10461049 fn clone_test ( ) {
10471050 let cert_chain = Certificate :: from_pem ( TEST_CERT_PEM . as_bytes ( ) ) . unwrap ( ) ;
@@ -1050,7 +1053,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
10501053 chain. push ( cert_chain. clone ( ) ) ;
10511054 chain. push ( cert_chain. clone ( ) ) ;
10521055 chain. push ( cert_chain) ;
1053-
1056+
10541057 let clone = chain. clone ( ) ;
10551058 let mut it = clone. iter ( ) ;
10561059
@@ -1085,7 +1088,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
10851088 let c1_info = format ! ( "{:?}" , c1. iter( ) . next( ) . unwrap( ) ) ;
10861089 let c2_info = format ! ( "{:?}" , c2. iter( ) . next( ) . unwrap( ) ) ;
10871090 let c3_info = format ! ( "{:?}" , c3. iter( ) . next( ) . unwrap( ) ) ;
1088-
1091+
10891092 chain. append ( c1. clone ( ) ) ;
10901093 chain. append ( c2. clone ( ) ) ;
10911094 chain. append ( c3. clone ( ) ) ;
@@ -1105,7 +1108,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
11051108 assert_eq ! ( c2_info, format!( "{:?}" , it. next( ) . unwrap( ) ) ) ;
11061109 assert ! ( it. next( ) . is_none( ) ) ;
11071110 }
1108-
1111+
11091112 chain. append ( c3. clone ( ) ) ;
11101113 chain. append ( c1. clone ( ) ) ;
11111114 {
@@ -1133,7 +1136,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
11331136 let mut it = chain. iter ( ) ;
11341137 assert ! ( it. next( ) . is_none( ) ) ;
11351138 }
1136-
1139+
11371140 assert ! ( chain. pop_back( ) . is_none( ) ) ;
11381141 {
11391142 let mut it = chain. iter ( ) ;
@@ -1167,7 +1170,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
11671170 let c1_info = format ! ( "{:?}" , c1) ;
11681171 let c2_info = format ! ( "{:?}" , c2) ;
11691172 let c3_info = format ! ( "{:?}" , c3) ;
1170-
1173+
11711174 chain. push ( c1. clone ( ) ) ;
11721175 chain. push ( c2. clone ( ) ) ;
11731176 chain. push ( c3. clone ( ) ) ;
@@ -1187,7 +1190,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
11871190 assert_eq ! ( c3_info, format!( "{:?}" , it. next( ) . unwrap( ) ) ) ;
11881191 assert ! ( it. next( ) . is_none( ) ) ;
11891192 }
1190-
1193+
11911194 chain. push ( c3. clone ( ) ) ;
11921195 chain. push ( c1. clone ( ) ) ;
11931196 {
@@ -1215,7 +1218,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
12151218 let mut it = chain. iter ( ) ;
12161219 assert ! ( it. next( ) . is_none( ) ) ;
12171220 }
1218-
1221+
12191222 assert ! ( chain. pop_front( ) . is_none( ) ) ;
12201223 {
12211224 let mut it = chain. iter ( ) ;
@@ -1302,7 +1305,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13021305 }
13031306
13041307 let clone = chain. clone ( ) ;
1305-
1308+
13061309 {
13071310 let mut it = chain. into_iter ( ) ;
13081311 assert_eq ! ( c1_info, format!( "{:?}" , it. next( ) . unwrap( ) ) ) ;
@@ -1331,7 +1334,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13311334 <& mut Option < MbedtlsBox < _ > > as UnsafeFrom < _ > >:: from ( ptr_test) . unwrap ( )
13321335 } ;
13331336 assert ! ( option. is_none( ) ) ;
1334-
1337+
13351338 let cert_list : Option < & mut MbedtlsList < Certificate > > = unsafe { UnsafeFrom :: from ( ptr_test) } ;
13361339 assert ! ( cert_list. is_none( ) ) ;
13371340
@@ -1341,7 +1344,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13411344 assert ! ( cert_list. is_none( ) ) ;
13421345
13431346
1344-
1347+
13451348 }
13461349
13471350 #[ test]
@@ -1358,7 +1361,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13581361
13591362 // Using debug strings so failing unit tests can identify any issue with contents.
13601363 let c1_info = format ! ( "{:?}" , c1) ;
1361-
1364+
13621365 chain. push ( c1. clone ( ) ) ;
13631366 chain. push ( c2. clone ( ) ) ;
13641367 chain. push ( c3. clone ( ) ) ;
@@ -1375,7 +1378,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13751378 assert_eq ! ( ( * cert) . inner. next, :: core:: ptr:: null_mut( ) ) ;
13761379 assert_eq ! ( c1_info, format!( "{:?}" , cert) ) ;
13771380
1378-
1381+
13791382 let cert = chain. clone ( ) . into_iter ( ) . next ( ) . unwrap ( ) ;
13801383
13811384 // Using into_iter and extracting a certificate must have its next set to null
@@ -1406,7 +1409,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
14061409
14071410 let cert : & Certificate = unsafe { UnsafeFrom :: from ( ptr) . unwrap ( ) } ;
14081411 assert_eq ! ( c1_info, format!( "{:?}" , cert) ) ;
1409-
1412+
14101413 let ptr : * mut x509_crt = ( & mut chain) . into ( ) ;
14111414 assert_ne ! ( ptr, :: core:: ptr:: null_mut( ) ) ;
14121415
@@ -1424,6 +1427,34 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
14241427 assert ! ( crate :: tests:: TestTrait :: <dyn Sync , MbedtlsList <Certificate >>:: new( ) . impls_trait( ) , "MbedtlsList<Certificate> should be Sync" ) ;
14251428 }
14261429
1430+ #[ test]
1431+ fn empty_cert_chain_test ( ) {
1432+ const C_CERT : & ' static str = concat ! ( include_str!( "../../tests/data/certificate.crt" ) , "\0 " ) ;
1433+ const C_ROOT : & ' static str = concat ! ( include_str!( "../../tests/data/root.crt" ) , "\0 " ) ;
1434+
1435+ let mut certs = MbedtlsList :: new ( ) ;
1436+ certs. push ( Certificate :: from_pem ( & C_CERT . as_bytes ( ) ) . unwrap ( ) ) ;
1437+ let mut roots = MbedtlsList :: new ( ) ;
1438+ roots. push ( Certificate :: from_pem ( & C_ROOT . as_bytes ( ) ) . unwrap ( ) ) ;
1439+
1440+ assert ! ( Certificate :: verify( & certs, & roots, None , None ) . is_ok( ) ) ;
1441+
1442+ let empty_certs = MbedtlsList :: new ( ) ;
1443+
1444+ assert_eq ! (
1445+ Certificate :: verify( & certs, & empty_certs, None , None ) . unwrap_err( ) ,
1446+ codes:: X509CertVerifyFailed . into( )
1447+ ) ;
1448+ assert_eq ! (
1449+ Certificate :: verify( & empty_certs, & roots, None , None ) . unwrap_err( ) ,
1450+ codes:: X509BadInputData . into( )
1451+ ) ;
1452+ assert_eq ! (
1453+ Certificate :: verify( & empty_certs, & empty_certs, None , None ) . unwrap_err( ) ,
1454+ codes:: X509BadInputData . into( )
1455+ ) ;
1456+ }
1457+
14271458 #[ test]
14281459 fn empty_crl_test ( ) {
14291460 const C_CERT : & ' static str = concat ! ( include_str!( "../../tests/data/certificate.crt" ) , "\0 " ) ;
0 commit comments