1313// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
1414
1515use  core:: default:: Default ; 
16+ use  core:: ops:: ControlFlow ; 
1617
1718use  crate :: { 
1819    cert:: { self ,  Cert ,  EndEntityOrCa } , 
@@ -38,6 +39,10 @@ pub(crate) fn build_chain(
3839        0 , 
3940        & mut  Budget :: default ( ) , 
4041    ) 
42+     . map_err ( |e| match  e { 
43+         ControlFlow :: Break ( err)  => err, 
44+         ControlFlow :: Continue ( err)  => err, 
45+     } ) 
4146} 
4247
4348#[ allow( clippy:: too_many_arguments) ]  
@@ -50,7 +55,7 @@ fn build_chain_inner(
5055    time :  time:: Time , 
5156    sub_ca_count :  usize , 
5257    budget :  & mut  Budget , 
53- )  -> Result < ( ) ,  Error >  { 
58+ )  -> Result < ( ) ,  ControlFlow < Error ,   Error > >  { 
5459    let  used_as_ca = used_as_ca ( & cert. ee_or_ca ) ; 
5560
5661    check_issuer_independent_properties ( 
@@ -68,7 +73,7 @@ fn build_chain_inner(
6873            const  MAX_SUB_CA_COUNT :  usize  = 6 ; 
6974
7075            if  sub_ca_count >= MAX_SUB_CA_COUNT  { 
71-                 return  Err ( Error :: MaximumPathDepthExceeded ) ; 
76+                 return  Err ( Error :: MaximumPathDepthExceeded . into ( ) ) ; 
7277            } 
7378        } 
7479        UsedAsCa :: No  => { 
@@ -91,7 +96,7 @@ fn build_chain_inner(
9196    let  result = loop_while_non_fatal_error ( trust_anchors,  |trust_anchor :  & TrustAnchor | { 
9297        let  trust_anchor_subject = untrusted:: Input :: from ( trust_anchor. subject ) ; 
9398        if  cert. issuer  != trust_anchor_subject { 
94-             return  Err ( Error :: UnknownIssuer ) ; 
99+             return  Err ( Error :: UnknownIssuer . into ( ) ) ; 
95100        } 
96101
97102        // TODO: check_distrust(trust_anchor_subject, trust_anchor_spki)?; 
@@ -113,17 +118,17 @@ fn build_chain_inner(
113118    match  result { 
114119        Ok ( ( ) )  => return  Ok ( ( ) ) , 
115120        // Fatal errors should halt further path building. 
116-         res @ Err ( err )   if  err . is_fatal ( )  => return  res, 
121+         res @ Err ( ControlFlow :: Break ( _ ) )  => return  res, 
117122        // Non-fatal errors should allow path building to continue. 
118-         _  => { } 
123+         Err ( ControlFlow :: Continue ( _ ) )  => { } 
119124    } ; 
120125
121126    loop_while_non_fatal_error ( intermediate_certs,  |cert_der| { 
122127        let  potential_issuer =
123128            cert:: parse_cert ( untrusted:: Input :: from ( cert_der) ,  EndEntityOrCa :: Ca ( cert) ) ?; 
124129
125130        if  potential_issuer. subject  != cert. issuer  { 
126-             return  Err ( Error :: UnknownIssuer ) ; 
131+             return  Err ( Error :: UnknownIssuer . into ( ) ) ; 
127132        } 
128133
129134        // Prevent loops; see RFC 4158 section 5.2. 
@@ -132,7 +137,7 @@ fn build_chain_inner(
132137            if  potential_issuer. spki . value ( )  == prev. spki . value ( ) 
133138                && potential_issuer. subject  == prev. subject 
134139            { 
135-                 return  Err ( Error :: UnknownIssuer ) ; 
140+                 return  Err ( Error :: UnknownIssuer . into ( ) ) ; 
136141            } 
137142            match  & prev. ee_or_ca  { 
138143                EndEntityOrCa :: EndEntity  => { 
@@ -168,7 +173,7 @@ fn check_signed_chain(
168173    cert_chain :  & Cert , 
169174    trust_anchor_key :  untrusted:: Input , 
170175    budget :  & mut  Budget , 
171- )  -> Result < ( ) ,  Error >  { 
176+ )  -> Result < ( ) ,  ControlFlow < Error ,   Error > >  { 
172177    let  mut  spki_value = trust_anchor_key; 
173178    let  mut  cert = cert_chain; 
174179    loop  { 
@@ -195,7 +200,7 @@ fn check_signed_chain_name_constraints(
195200    trust_anchor :  & TrustAnchor , 
196201    subject_common_name_contents :  subject_name:: SubjectCommonNameContents , 
197202    budget :  & mut  Budget , 
198- )  -> Result < ( ) ,  Error >  { 
203+ )  -> Result < ( ) ,  ControlFlow < Error ,   Error > >  { 
199204    let  mut  cert = cert_chain; 
200205    let  mut  name_constraints = trust_anchor
201206        . name_constraints 
@@ -455,8 +460,8 @@ fn check_eku(
455460
456461fn  loop_while_non_fatal_error < V > ( 
457462    values :  V , 
458-     mut  f :  impl  FnMut ( V :: Item )  -> Result < ( ) ,  Error > , 
459- )  -> Result < ( ) ,  Error > 
463+     mut  f :  impl  FnMut ( V :: Item )  -> Result < ( ) ,  ControlFlow < Error ,   Error > > , 
464+ )  -> Result < ( ) ,  ControlFlow < Error ,   Error > > 
460465where 
461466    V :  IntoIterator , 
462467{ 
@@ -465,12 +470,12 @@ where
465470        match  f ( v)  { 
466471            Ok ( ( ) )  => return  Ok ( ( ) ) , 
467472            // Fatal errors should halt further looping. 
468-             res @ Err ( err )   if  err . is_fatal ( )  => return  res, 
473+             res @ Err ( ControlFlow :: Break ( _ ) )  => return  res, 
469474            // Non-fatal errors should allow looping to continue. 
470-             _  => { } 
475+             Err ( ControlFlow :: Continue ( _ ) )  => { } 
471476        } 
472477    } 
473-     Err ( Error :: UnknownIssuer ) 
478+     Err ( Error :: UnknownIssuer . into ( ) ) 
474479} 
475480
476481#[ cfg( test) ]  
@@ -489,7 +494,7 @@ mod tests {
489494        intermediate_count :  usize , 
490495        trust_anchor_is_actual_issuer :  TrustAnchorIsActualIssuer , 
491496        budget :  Option < Budget > , 
492-     )  -> Error  { 
497+     )  -> ControlFlow < Error ,   Error >  { 
493498        let  ca_cert = make_issuer ( "Bogus Subject" ,  None ) ; 
494499        let  ca_cert_der = ca_cert. serialize_der ( ) . unwrap ( ) ; 
495500
@@ -518,16 +523,16 @@ mod tests {
518523    #[ test]  
519524    #[ cfg( feature = "alloc" ) ]  
520525    fn  test_too_many_signatures ( )  { 
521-         assert_eq ! ( 
526+         assert ! ( matches !( 
522527            build_degenerate_chain( 5 ,  TrustAnchorIsActualIssuer :: Yes ,  None ) , 
523-             Error :: MaximumSignatureChecksExceeded 
524-         ) ; 
528+             ControlFlow :: Break ( Error :: MaximumSignatureChecksExceeded ) 
529+         ) ) ; 
525530    } 
526531
527532    #[ test]  
528533    #[ cfg( feature = "alloc" ) ]  
529534    fn  test_too_many_path_calls ( )  { 
530-         assert_eq ! ( 
535+         assert ! ( matches !( 
531536            build_degenerate_chain( 
532537                10 , 
533538                TrustAnchorIsActualIssuer :: No , 
@@ -539,12 +544,12 @@ mod tests {
539544                    ..Budget :: default ( ) 
540545                } ) 
541546            ) , 
542-             Error :: MaximumPathBuildCallsExceeded 
543-         ) ; 
547+             ControlFlow :: Break ( Error :: MaximumPathBuildCallsExceeded ) 
548+         ) ) ; 
544549    } 
545550
546551    #[ cfg( feature = "alloc" ) ]  
547-     fn  build_linear_chain ( chain_length :  usize )  -> Result < ( ) ,  Error >  { 
552+     fn  build_linear_chain ( chain_length :  usize )  -> Result < ( ) ,  ControlFlow < Error ,   Error > >  { 
548553        let  ca_cert = make_issuer ( format ! ( "Bogus Subject {chain_length}" ) ,  None ) ; 
549554        let  ca_cert_der = ca_cert. serialize_der ( ) . unwrap ( ) ; 
550555
@@ -568,20 +573,23 @@ mod tests {
568573    #[ test]  
569574    #[ cfg( feature = "alloc" ) ]  
570575    fn  longest_allowed_path ( )  { 
571-         assert_eq ! ( build_linear_chain( 1 ) ,   Ok ( ( ) ) ) ; 
572-         assert_eq ! ( build_linear_chain( 2 ) ,   Ok ( ( ) ) ) ; 
573-         assert_eq ! ( build_linear_chain( 3 ) ,   Ok ( ( ) ) ) ; 
574-         assert_eq ! ( build_linear_chain( 4 ) ,   Ok ( ( ) ) ) ; 
575-         assert_eq ! ( build_linear_chain( 5 ) ,   Ok ( ( ) ) ) ; 
576-         assert_eq ! ( build_linear_chain( 6 ) ,   Ok ( ( ) ) ) ; 
576+         assert ! ( build_linear_chain( 1 ) . is_ok ( ) ) ; 
577+         assert ! ( build_linear_chain( 2 ) . is_ok ( ) ) ; 
578+         assert ! ( build_linear_chain( 3 ) . is_ok ( ) ) ; 
579+         assert ! ( build_linear_chain( 4 ) . is_ok ( ) ) ; 
580+         assert ! ( build_linear_chain( 5 ) . is_ok ( ) ) ; 
581+         assert ! ( build_linear_chain( 6 ) . is_ok ( ) ) ; 
577582    } 
578583
579584    #[ test]  
580585    #[ cfg( feature = "alloc" ) ]  
581586    fn  path_too_long ( )  { 
582587        // Note: webpki 0.101.x and earlier surface all non-fatal errors as UnknownIssuer, 
583588        //       eating the more specific MaximumPathDepthExceeded error. 
584-         assert_eq ! ( build_linear_chain( 7 ) ,  Err ( Error :: UnknownIssuer ) ) ; 
589+         assert ! ( matches!( 
590+             build_linear_chain( 7 ) , 
591+             Err ( ControlFlow :: Continue ( Error :: UnknownIssuer ) ) 
592+         ) ) ; 
585593    } 
586594
587595    #[ test]  
@@ -631,13 +639,13 @@ mod tests {
631639        // Validation should succeed with the name constraint comparison budget allocated above. 
632640        // This shows that we're not consuming budget on unused intermediates: we didn't budget 
633641        // enough comparisons for that to pass the overall chain building. 
634-         verify_chain ( 
642+         assert ! ( verify_chain( 
635643            & ca_cert_der, 
636644            & intermediates_der, 
637645            & ee_cert, 
638646            Some ( passing_budget) , 
639647        ) 
640-         . unwrap ( ) ; 
648+         . is_ok ( ) ) ; 
641649
642650        let  failing_budget = Budget  { 
643651            // See passing_budget: 2 comparisons is not sufficient. 
@@ -654,7 +662,12 @@ mod tests {
654662            Some ( failing_budget) , 
655663        ) ; 
656664
657-         assert_eq ! ( result,  Err ( Error :: MaximumNameConstraintComparisonsExceeded ) ) ; 
665+         assert ! ( matches!( 
666+             result, 
667+             Err ( ControlFlow :: Break ( 
668+                 Error :: MaximumNameConstraintComparisonsExceeded 
669+             ) ) 
670+         ) ) ; 
658671    } 
659672
660673    #[ cfg( feature = "alloc" ) ]  
@@ -663,7 +676,7 @@ mod tests {
663676        intermediates_der :  & [ Vec < u8 > ] , 
664677        ee_cert_der :  & [ u8 ] , 
665678        budget :  Option < Budget > , 
666-     )  -> Result < ( ) ,  Error >  { 
679+     )  -> Result < ( ) ,  ControlFlow < Error ,   Error > >  { 
667680        use  crate :: ECDSA_P256_SHA256 ; 
668681        use  crate :: { EndEntityCert ,  Time } ; 
669682
0 commit comments