1 /*
2 * SecureQueue
3 * (C) 1999-2007 Jack Lloyd
4 *     2012 Markus Wanner
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/secqueue.h>
10 #include <algorithm>
11 
12 namespace Botan {
13 
14 /**
15 * A node in a SecureQueue
16 */
17 class SecureQueueNode final
18    {
19    public:
SecureQueueNode()20       SecureQueueNode() : m_buffer(BOTAN_DEFAULT_BUFFER_SIZE)
21          { m_next = nullptr; m_start = m_end = 0; }
22 
~SecureQueueNode()23       ~SecureQueueNode() { m_next = nullptr; m_start = m_end = 0; }
24 
write(const uint8_t input[],size_t length)25       size_t write(const uint8_t input[], size_t length)
26          {
27          size_t copied = std::min<size_t>(length, m_buffer.size() - m_end);
28          copy_mem(m_buffer.data() + m_end, input, copied);
29          m_end += copied;
30          return copied;
31          }
32 
read(uint8_t output[],size_t length)33       size_t read(uint8_t output[], size_t length)
34          {
35          size_t copied = std::min(length, m_end - m_start);
36          copy_mem(output, m_buffer.data() + m_start, copied);
37          m_start += copied;
38          return copied;
39          }
40 
peek(uint8_t output[],size_t length,size_t offset=0)41       size_t peek(uint8_t output[], size_t length, size_t offset = 0)
42          {
43          const size_t left = m_end - m_start;
44          if(offset >= left) return 0;
45          size_t copied = std::min(length, left - offset);
46          copy_mem(output, m_buffer.data() + m_start + offset, copied);
47          return copied;
48          }
49 
size() const50       size_t size() const { return (m_end - m_start); }
51    private:
52       friend class SecureQueue;
53       SecureQueueNode* m_next;
54       secure_vector<uint8_t> m_buffer;
55       size_t m_start, m_end;
56    };
57 
58 /*
59 * Create a SecureQueue
60 */
SecureQueue()61 SecureQueue::SecureQueue()
62    {
63    m_bytes_read = 0;
64    set_next(nullptr, 0);
65    m_head = m_tail = new SecureQueueNode;
66    }
67 
68 /*
69 * Copy a SecureQueue
70 */
SecureQueue(const SecureQueue & input)71 SecureQueue::SecureQueue(const SecureQueue& input) :
72    Fanout_Filter(), DataSource()
73    {
74    m_bytes_read = 0;
75    set_next(nullptr, 0);
76 
77    m_head = m_tail = new SecureQueueNode;
78    SecureQueueNode* temp = input.m_head;
79    while(temp)
80       {
81       write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start);
82       temp = temp->m_next;
83       }
84    }
85 
86 /*
87 * Destroy this SecureQueue
88 */
destroy()89 void SecureQueue::destroy()
90    {
91    SecureQueueNode* temp = m_head;
92    while(temp)
93       {
94       SecureQueueNode* holder = temp->m_next;
95       delete temp;
96       temp = holder;
97       }
98    m_head = m_tail = nullptr;
99    }
100 
101 /*
102 * Copy a SecureQueue
103 */
operator =(const SecureQueue & input)104 SecureQueue& SecureQueue::operator=(const SecureQueue& input)
105    {
106    if(this == &input)
107       return *this;
108 
109    destroy();
110    m_bytes_read = input.get_bytes_read();
111    m_head = m_tail = new SecureQueueNode;
112    SecureQueueNode* temp = input.m_head;
113    while(temp)
114       {
115       write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start);
116       temp = temp->m_next;
117       }
118    return (*this);
119    }
120 
121 /*
122 * Add some bytes to the queue
123 */
write(const uint8_t input[],size_t length)124 void SecureQueue::write(const uint8_t input[], size_t length)
125    {
126    if(!m_head)
127       m_head = m_tail = new SecureQueueNode;
128    while(length)
129       {
130       const size_t n = m_tail->write(input, length);
131       input += n;
132       length -= n;
133       if(length)
134          {
135          m_tail->m_next = new SecureQueueNode;
136          m_tail = m_tail->m_next;
137          }
138       }
139    }
140 
141 /*
142 * Read some bytes from the queue
143 */
read(uint8_t output[],size_t length)144 size_t SecureQueue::read(uint8_t output[], size_t length)
145    {
146    size_t got = 0;
147    while(length && m_head)
148       {
149       const size_t n = m_head->read(output, length);
150       output += n;
151       got += n;
152       length -= n;
153       if(m_head->size() == 0)
154          {
155          SecureQueueNode* holder = m_head->m_next;
156          delete m_head;
157          m_head = holder;
158          }
159       }
160    m_bytes_read += got;
161    return got;
162    }
163 
164 /*
165 * Read data, but do not remove it from queue
166 */
peek(uint8_t output[],size_t length,size_t offset) const167 size_t SecureQueue::peek(uint8_t output[], size_t length, size_t offset) const
168    {
169    SecureQueueNode* current = m_head;
170 
171    while(offset && current)
172       {
173       if(offset >= current->size())
174          {
175          offset -= current->size();
176          current = current->m_next;
177          }
178       else
179          break;
180       }
181 
182    size_t got = 0;
183    while(length && current)
184       {
185       const size_t n = current->peek(output, length, offset);
186       offset = 0;
187       output += n;
188       got += n;
189       length -= n;
190       current = current->m_next;
191       }
192    return got;
193    }
194 
195 /**
196 * Return how many bytes have been read so far.
197 */
get_bytes_read() const198 size_t SecureQueue::get_bytes_read() const
199    {
200    return m_bytes_read;
201    }
202 
203 /*
204 * Return how many bytes the queue holds
205 */
size() const206 size_t SecureQueue::size() const
207    {
208    SecureQueueNode* current = m_head;
209    size_t count = 0;
210 
211    while(current)
212       {
213       count += current->size();
214       current = current->m_next;
215       }
216    return count;
217    }
218 
219 /*
220 * Test if the queue has any data in it
221 */
end_of_data() const222 bool SecureQueue::end_of_data() const
223    {
224    return (size() == 0);
225    }
226 
empty() const227 bool SecureQueue::empty() const
228    {
229    return (size() == 0);
230    }
231 
232 }
233