@@ -761,6 +761,50 @@ impl EchConfigListBytes<'_> {
761761 }
762762}
763763
764+ #[ cfg( feature = "alloc" ) ]
765+ impl EchConfigListBytes < ' static > {
766+ /// Convert an iterator over PEM items into an `EchConfigListBytes` and private key.
767+ ///
768+ /// This handles the "ECHConfig file" format specified in
769+ /// <https://www.ietf.org/archive/id/draft-farrell-tls-pemesni-05.html#name-echconfig-file>
770+ ///
771+ /// Use it like:
772+ ///
773+ /// ```rust
774+ /// # #[cfg(all(feature = "alloc", feature = "std"))] {
775+ /// # use rustls_pki_types::{EchConfigListBytes, pem::PemObject};
776+ /// let (config, key) = EchConfigListBytes::config_and_key_from_iter(
777+ /// PemObject::pem_file_iter("tests/data/ech.pem").unwrap()
778+ /// ).unwrap();
779+ /// # }
780+ /// ```
781+ pub fn config_and_key_from_iter (
782+ iter : impl Iterator < Item = Result < ( SectionKind , Vec < u8 > ) , pem:: Error > > ,
783+ ) -> Result < ( Self , PrivatePkcs8KeyDer < ' static > ) , pem:: Error > {
784+ let mut key = None ;
785+ let mut config = None ;
786+
787+ for item in iter {
788+ let ( kind, data) = item?;
789+ match kind {
790+ SectionKind :: PrivateKey => {
791+ key = PrivatePkcs8KeyDer :: from_pem ( kind, data) ;
792+ }
793+ SectionKind :: EchConfigList => {
794+ config = Self :: from_pem ( kind, data) ;
795+ }
796+ _ => continue ,
797+ } ;
798+
799+ if let ( Some ( _key) , Some ( _config) ) = ( & key, & config) {
800+ return Ok ( ( config. take ( ) . unwrap ( ) , key. take ( ) . unwrap ( ) ) ) ;
801+ }
802+ }
803+
804+ Err ( pem:: Error :: NoItemsFound )
805+ }
806+ }
807+
764808#[ cfg( feature = "alloc" ) ]
765809impl PemObjectFilter for EchConfigListBytes < ' static > {
766810 const KIND : SectionKind = SectionKind :: EchConfigList ;
0 commit comments