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