1 //! Streaming PEM reader. 2 3 use super::Reader; 4 use crate::{Decode, Error, ErrorKind, Header, Length, Result}; 5 use core::cell::RefCell; 6 7 #[allow(clippy::integer_arithmetic)] 8 mod utils { 9 use crate::{Error, Length, Result}; 10 use pem_rfc7468::Decoder; 11 12 #[derive(Clone)] 13 pub(super) struct BufReader<'i> { 14 /// Inner PEM decoder. 15 decoder: Decoder<'i>, 16 17 /// Remaining after base64 decoding 18 remaining: usize, 19 20 /// Read buffer 21 buf: [u8; BufReader::CAPACITY], 22 23 /// Position of the head in the buffer, 24 pos: usize, 25 26 /// Position of the tail in the buffer, 27 cap: usize, 28 } 29 30 impl<'i> BufReader<'i> { 31 const CAPACITY: usize = 256; 32 new(pem: &'i [u8]) -> Result<Self>33 pub fn new(pem: &'i [u8]) -> Result<Self> { 34 let decoder = Decoder::new(pem)?; 35 let remaining = decoder.remaining_len(); 36 37 Ok(Self { 38 decoder, 39 remaining, 40 buf: [0u8; 256], 41 pos: 0, 42 cap: 0, 43 }) 44 } 45 remaining_len(&self) -> usize46 pub fn remaining_len(&self) -> usize { 47 self.decoder.remaining_len() + self.cap - self.pos 48 } 49 fill_buffer(&mut self) -> Result<()>50 fn fill_buffer(&mut self) -> Result<()> { 51 debug_assert!(self.pos <= self.cap); 52 53 if self.is_empty() { 54 self.pos = 0; 55 self.cap = 0; 56 } 57 58 let end = (self.cap + self.remaining).min(Self::CAPACITY); 59 let writable_slice = &mut self.buf[self.cap..end]; 60 if writable_slice.is_empty() { 61 return Ok(()); 62 } 63 64 let wrote = self.decoder.decode(writable_slice)?.len(); 65 if wrote == 0 { 66 return Err(Error::incomplete(Length::try_from(self.pos)?)); 67 } 68 69 self.cap += wrote; 70 self.remaining -= wrote; 71 debug_assert!(self.cap <= Self::CAPACITY); 72 73 Ok(()) 74 } 75 76 /// Get the PEM label which will be used in the encapsulation boundaries 77 /// for this document. type_label(&self) -> &'i str78 pub fn type_label(&self) -> &'i str { 79 self.decoder.type_label() 80 } 81 is_empty(&self) -> bool82 fn is_empty(&self) -> bool { 83 self.pos == self.cap 84 } 85 as_slice(&self) -> &[u8]86 fn as_slice(&self) -> &[u8] { 87 &self.buf[self.pos..self.cap] 88 } 89 } 90 91 impl<'i> BufReader<'i> { peek_byte(&self) -> Option<u8>92 pub fn peek_byte(&self) -> Option<u8> { 93 let s = self.as_slice(); 94 s.first().copied() 95 } 96 copy_to_slice<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]>97 pub fn copy_to_slice<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> { 98 let mut output_pos = 0; 99 100 while output_pos < buf.len() { 101 if self.is_empty() { 102 self.fill_buffer()?; 103 } 104 105 let available = &self.buf[self.pos..self.cap]; 106 let window_len = (buf.len() - output_pos).min(available.len()); 107 let window = &mut buf[output_pos..output_pos + window_len]; 108 109 window.copy_from_slice(&available[..window_len]); 110 self.pos += window_len; 111 output_pos += window_len; 112 } 113 114 // Don't leave the read buffer empty for peek_byte() 115 if self.is_empty() && self.decoder.remaining_len() != 0 { 116 self.fill_buffer()? 117 } 118 119 debug_assert_eq!(output_pos, buf.len()); 120 121 Ok(buf) 122 } 123 } 124 } 125 126 /// `Reader` type which decodes PEM on-the-fly. 127 #[cfg(feature = "pem")] 128 #[derive(Clone)] 129 pub struct PemReader<'i> { 130 /// Inner PEM decoder wrapped in a BufReader. 131 reader: RefCell<utils::BufReader<'i>>, 132 133 /// Input length (in bytes after Base64 decoding). 134 input_len: Length, 135 136 /// Position in the input buffer (in bytes after Base64 decoding). 137 position: Length, 138 } 139 140 #[cfg(feature = "pem")] 141 impl<'i> PemReader<'i> { 142 /// Create a new PEM reader which decodes data on-the-fly. 143 /// 144 /// Uses the default 64-character line wrapping. new(pem: &'i [u8]) -> Result<Self>145 pub fn new(pem: &'i [u8]) -> Result<Self> { 146 let reader = utils::BufReader::new(pem)?; 147 let input_len = Length::try_from(reader.remaining_len())?; 148 149 Ok(Self { 150 reader: RefCell::new(reader), 151 input_len, 152 position: Length::ZERO, 153 }) 154 } 155 156 /// Get the PEM label which will be used in the encapsulation boundaries 157 /// for this document. type_label(&self) -> &'i str158 pub fn type_label(&self) -> &'i str { 159 self.reader.borrow().type_label() 160 } 161 } 162 163 #[cfg(feature = "pem")] 164 impl<'i> Reader<'i> for PemReader<'i> { input_len(&self) -> Length165 fn input_len(&self) -> Length { 166 self.input_len 167 } 168 peek_byte(&self) -> Option<u8>169 fn peek_byte(&self) -> Option<u8> { 170 if self.is_finished() { 171 None 172 } else { 173 self.reader.borrow().peek_byte() 174 } 175 } 176 peek_header(&self) -> Result<Header>177 fn peek_header(&self) -> Result<Header> { 178 if self.is_finished() { 179 Err(Error::incomplete(self.offset())) 180 } else { 181 Header::decode(&mut self.clone()) 182 } 183 } 184 position(&self) -> Length185 fn position(&self) -> Length { 186 self.position 187 } 188 read_slice(&mut self, _len: Length) -> Result<&'i [u8]>189 fn read_slice(&mut self, _len: Length) -> Result<&'i [u8]> { 190 // Can't borrow from PEM because it requires decoding 191 Err(ErrorKind::Reader.into()) 192 } 193 read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]>194 fn read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> { 195 let bytes = self.reader.borrow_mut().copy_to_slice(buf)?; 196 197 self.position = (self.position + bytes.len())?; 198 199 debug_assert_eq!( 200 self.position, 201 (self.input_len - Length::try_from(self.reader.borrow().remaining_len())?)? 202 ); 203 204 Ok(bytes) 205 } 206 } 207