summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/filters/secqueue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/filters/secqueue.cpp')
-rw-r--r--comm/third_party/botan/src/lib/filters/secqueue.cpp232
1 files changed, 232 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/filters/secqueue.cpp b/comm/third_party/botan/src/lib/filters/secqueue.cpp
new file mode 100644
index 0000000000..1c8d281493
--- /dev/null
+++ b/comm/third_party/botan/src/lib/filters/secqueue.cpp
@@ -0,0 +1,232 @@
+/*
+* SecureQueue
+* (C) 1999-2007 Jack Lloyd
+* 2012 Markus Wanner
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/secqueue.h>
+#include <algorithm>
+
+namespace Botan {
+
+/**
+* A node in a SecureQueue
+*/
+class SecureQueueNode final
+ {
+ public:
+ SecureQueueNode() : m_buffer(BOTAN_DEFAULT_BUFFER_SIZE)
+ { m_next = nullptr; m_start = m_end = 0; }
+
+ ~SecureQueueNode() { m_next = nullptr; m_start = m_end = 0; }
+
+ size_t write(const uint8_t input[], size_t length)
+ {
+ size_t copied = std::min<size_t>(length, m_buffer.size() - m_end);
+ copy_mem(m_buffer.data() + m_end, input, copied);
+ m_end += copied;
+ return copied;
+ }
+
+ size_t read(uint8_t output[], size_t length)
+ {
+ size_t copied = std::min(length, m_end - m_start);
+ copy_mem(output, m_buffer.data() + m_start, copied);
+ m_start += copied;
+ return copied;
+ }
+
+ size_t peek(uint8_t output[], size_t length, size_t offset = 0)
+ {
+ const size_t left = m_end - m_start;
+ if(offset >= left) return 0;
+ size_t copied = std::min(length, left - offset);
+ copy_mem(output, m_buffer.data() + m_start + offset, copied);
+ return copied;
+ }
+
+ size_t size() const { return (m_end - m_start); }
+ private:
+ friend class SecureQueue;
+ SecureQueueNode* m_next;
+ secure_vector<uint8_t> m_buffer;
+ size_t m_start, m_end;
+ };
+
+/*
+* Create a SecureQueue
+*/
+SecureQueue::SecureQueue()
+ {
+ m_bytes_read = 0;
+ set_next(nullptr, 0);
+ m_head = m_tail = new SecureQueueNode;
+ }
+
+/*
+* Copy a SecureQueue
+*/
+SecureQueue::SecureQueue(const SecureQueue& input) :
+ Fanout_Filter(), DataSource()
+ {
+ m_bytes_read = 0;
+ set_next(nullptr, 0);
+
+ m_head = m_tail = new SecureQueueNode;
+ SecureQueueNode* temp = input.m_head;
+ while(temp)
+ {
+ write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start);
+ temp = temp->m_next;
+ }
+ }
+
+/*
+* Destroy this SecureQueue
+*/
+void SecureQueue::destroy()
+ {
+ SecureQueueNode* temp = m_head;
+ while(temp)
+ {
+ SecureQueueNode* holder = temp->m_next;
+ delete temp;
+ temp = holder;
+ }
+ m_head = m_tail = nullptr;
+ }
+
+/*
+* Copy a SecureQueue
+*/
+SecureQueue& SecureQueue::operator=(const SecureQueue& input)
+ {
+ if(this == &input)
+ return *this;
+
+ destroy();
+ m_bytes_read = input.get_bytes_read();
+ m_head = m_tail = new SecureQueueNode;
+ SecureQueueNode* temp = input.m_head;
+ while(temp)
+ {
+ write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start);
+ temp = temp->m_next;
+ }
+ return (*this);
+ }
+
+/*
+* Add some bytes to the queue
+*/
+void SecureQueue::write(const uint8_t input[], size_t length)
+ {
+ if(!m_head)
+ m_head = m_tail = new SecureQueueNode;
+ while(length)
+ {
+ const size_t n = m_tail->write(input, length);
+ input += n;
+ length -= n;
+ if(length)
+ {
+ m_tail->m_next = new SecureQueueNode;
+ m_tail = m_tail->m_next;
+ }
+ }
+ }
+
+/*
+* Read some bytes from the queue
+*/
+size_t SecureQueue::read(uint8_t output[], size_t length)
+ {
+ size_t got = 0;
+ while(length && m_head)
+ {
+ const size_t n = m_head->read(output, length);
+ output += n;
+ got += n;
+ length -= n;
+ if(m_head->size() == 0)
+ {
+ SecureQueueNode* holder = m_head->m_next;
+ delete m_head;
+ m_head = holder;
+ }
+ }
+ m_bytes_read += got;
+ return got;
+ }
+
+/*
+* Read data, but do not remove it from queue
+*/
+size_t SecureQueue::peek(uint8_t output[], size_t length, size_t offset) const
+ {
+ SecureQueueNode* current = m_head;
+
+ while(offset && current)
+ {
+ if(offset >= current->size())
+ {
+ offset -= current->size();
+ current = current->m_next;
+ }
+ else
+ break;
+ }
+
+ size_t got = 0;
+ while(length && current)
+ {
+ const size_t n = current->peek(output, length, offset);
+ offset = 0;
+ output += n;
+ got += n;
+ length -= n;
+ current = current->m_next;
+ }
+ return got;
+ }
+
+/**
+* Return how many bytes have been read so far.
+*/
+size_t SecureQueue::get_bytes_read() const
+ {
+ return m_bytes_read;
+ }
+
+/*
+* Return how many bytes the queue holds
+*/
+size_t SecureQueue::size() const
+ {
+ SecureQueueNode* current = m_head;
+ size_t count = 0;
+
+ while(current)
+ {
+ count += current->size();
+ current = current->m_next;
+ }
+ return count;
+ }
+
+/*
+* Test if the queue has any data in it
+*/
+bool SecureQueue::end_of_data() const
+ {
+ return (size() == 0);
+ }
+
+bool SecureQueue::empty() const
+ {
+ return (size() == 0);
+ }
+
+}