@@ -100,7 +100,7 @@ impl Identity {
100100
101101 pub fn from_pkcs8 ( pem : & [ u8 ] , key : & [ u8 ] ) -> Result < Identity , Error > {
102102 let mut store = Memory :: new ( ) ?. into_store ( ) ;
103- let mut cert_iter = crate :: pem:: PemBlock :: new ( pem) . into_iter ( ) ;
103+ let mut cert_iter = pem:: PemBlock :: new ( pem) . into_iter ( ) ;
104104 let leaf = cert_iter. next ( ) . expect ( "at least one certificate must be provided to create an identity" ) ;
105105 let cert = CertContext :: from_pem ( std:: str:: from_utf8 ( leaf) . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: InvalidInput , "leaf cert contains invalid utf8" ) ) ?) ?;
106106
@@ -378,3 +378,84 @@ impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
378378 self . 0 . flush ( )
379379 }
380380}
381+
382+
383+ mod pem {
384+ /// Split data by PEM guard lines
385+ pub struct PemBlock < ' a > {
386+ pem_block : & ' a str ,
387+ cur_end : usize ,
388+ }
389+
390+ impl < ' a > PemBlock < ' a > {
391+ pub fn new ( data : & ' a [ u8 ] ) -> PemBlock < ' a > {
392+ let s = :: std:: str:: from_utf8 ( data) . unwrap ( ) ;
393+ PemBlock {
394+ pem_block : s,
395+ cur_end : s. find ( "-----BEGIN" ) . unwrap_or ( s. len ( ) ) ,
396+ }
397+ }
398+ }
399+
400+ impl < ' a > Iterator for PemBlock < ' a > {
401+ type Item = & ' a [ u8 ] ;
402+ fn next ( & mut self ) -> Option < Self :: Item > {
403+ let last = self . pem_block . len ( ) ;
404+ if self . cur_end >= last {
405+ return None ;
406+ }
407+ let begin = self . cur_end ;
408+ let pos = self . pem_block [ begin + 1 ..] . find ( "-----BEGIN" ) ;
409+ self . cur_end = match pos {
410+ Some ( end) => end + begin + 1 ,
411+ None => last,
412+ } ;
413+ return Some ( & self . pem_block [ begin..self . cur_end ] . as_bytes ( ) ) ;
414+ }
415+ }
416+
417+ #[ test]
418+ fn test_split ( ) {
419+ // Split three certs, CRLF line terminators.
420+ assert_eq ! ( PemBlock :: new( b"-----BEGIN FIRST-----\r \n -----END FIRST-----\r \n \
421+ -----BEGIN SECOND-----\r \n -----END SECOND\r \n \
422+ -----BEGIN THIRD-----\r \n -----END THIRD\r \n ") . collect:: <Vec <& [ u8 ] >>( ) ,
423+ vec![ b"-----BEGIN FIRST-----\r \n -----END FIRST-----\r \n " as & [ u8 ] ,
424+ b"-----BEGIN SECOND-----\r \n -----END SECOND\r \n " ,
425+ b"-----BEGIN THIRD-----\r \n -----END THIRD\r \n " ] ) ;
426+ // Split three certs, CRLF line terminators except at EOF.
427+ assert_eq ! ( PemBlock :: new( b"-----BEGIN FIRST-----\r \n -----END FIRST-----\r \n \
428+ -----BEGIN SECOND-----\r \n -----END SECOND-----\r \n \
429+ -----BEGIN THIRD-----\r \n -----END THIRD-----") . collect:: <Vec <& [ u8 ] >>( ) ,
430+ vec![ b"-----BEGIN FIRST-----\r \n -----END FIRST-----\r \n " as & [ u8 ] ,
431+ b"-----BEGIN SECOND-----\r \n -----END SECOND-----\r \n " ,
432+ b"-----BEGIN THIRD-----\r \n -----END THIRD-----" ] ) ;
433+ // Split two certs, LF line terminators.
434+ assert_eq ! ( PemBlock :: new( b"-----BEGIN FIRST-----\n -----END FIRST-----\n \
435+ -----BEGIN SECOND-----\n -----END SECOND\n ") . collect:: <Vec <& [ u8 ] >>( ) ,
436+ vec![ b"-----BEGIN FIRST-----\n -----END FIRST-----\n " as & [ u8 ] ,
437+ b"-----BEGIN SECOND-----\n -----END SECOND\n " ] ) ;
438+ // Split two certs, CR line terminators.
439+ assert_eq ! ( PemBlock :: new( b"-----BEGIN FIRST-----\r -----END FIRST-----\r \
440+ -----BEGIN SECOND-----\r -----END SECOND\r ") . collect:: <Vec <& [ u8 ] >>( ) ,
441+ vec![ b"-----BEGIN FIRST-----\r -----END FIRST-----\r " as & [ u8 ] ,
442+ b"-----BEGIN SECOND-----\r -----END SECOND\r " ] ) ;
443+ // Split two certs, LF line terminators except at EOF.
444+ assert_eq ! ( PemBlock :: new( b"-----BEGIN FIRST-----\n -----END FIRST-----\n \
445+ -----BEGIN SECOND-----\n -----END SECOND") . collect:: <Vec <& [ u8 ] >>( ) ,
446+ vec![ b"-----BEGIN FIRST-----\n -----END FIRST-----\n " as & [ u8 ] ,
447+ b"-----BEGIN SECOND-----\n -----END SECOND" ] ) ;
448+ // Split a single cert, LF line terminators.
449+ assert_eq ! ( PemBlock :: new( b"-----BEGIN FIRST-----\n -----END FIRST-----\n " ) . collect:: <Vec <& [ u8 ] >>( ) ,
450+ vec![ b"-----BEGIN FIRST-----\n -----END FIRST-----\n " as & [ u8 ] ] ) ;
451+ // Split a single cert, LF line terminators except at EOF.
452+ assert_eq ! ( PemBlock :: new( b"-----BEGIN FIRST-----\n -----END FIRST-----" ) . collect:: <Vec <& [ u8 ] >>( ) ,
453+ vec![ b"-----BEGIN FIRST-----\n -----END FIRST-----" as & [ u8 ] ] ) ;
454+ // (Don't) split garbage.
455+ assert_eq ! ( PemBlock :: new( b"junk" ) . collect:: <Vec <& [ u8 ] >>( ) ,
456+ Vec :: <& [ u8 ] >:: new( ) ) ;
457+ assert_eq ! ( PemBlock :: new( b"junk-----BEGIN garbage" ) . collect:: <Vec <& [ u8 ] >>( ) ,
458+ vec![ b"-----BEGIN garbage" as & [ u8 ] ] ) ;
459+ }
460+ }
461+
0 commit comments