Botan 3.9.0
Crypto and TLS for C&
secqueue.cpp
Go to the documentation of this file.
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/internal/secqueue.h>
10
11#include <botan/mem_ops.h>
12#include <algorithm>
13
14namespace Botan {
15
16/**
17* A node in a SecureQueue
18*/
19class SecureQueueNode final {
20 public:
21 SecureQueueNode() : m_next(nullptr), m_buffer(DefaultBufferSize), m_start(0), m_end(0) {}
22
23 ~SecureQueueNode() {
24 m_next = nullptr;
25 m_start = m_end = 0;
26 }
27
28 SecureQueueNode(const SecureQueueNode& other) = delete;
29 SecureQueueNode(SecureQueueNode&& other) = delete;
30 SecureQueueNode& operator=(const SecureQueueNode& other) = delete;
31 SecureQueueNode& operator=(SecureQueueNode&& other) = delete;
32
33 size_t write(const uint8_t input[], size_t length) {
34 size_t copied = std::min<size_t>(length, m_buffer.size() - m_end);
35 copy_mem(m_buffer.data() + m_end, input, copied);
36 m_end += copied;
37 return copied;
38 }
39
40 size_t read(uint8_t output[], size_t length) {
41 size_t copied = std::min(length, m_end - m_start);
42 copy_mem(output, m_buffer.data() + m_start, copied);
43 m_start += copied;
44 return copied;
45 }
46
47 size_t peek(uint8_t output[], size_t length, size_t offset = 0) {
48 const size_t left = m_end - m_start;
49 if(offset >= left) {
50 return 0;
51 }
52 size_t copied = std::min(length, left - offset);
53 copy_mem(output, m_buffer.data() + m_start + offset, copied);
54 return copied;
55 }
56
57 size_t size() const { return (m_end - m_start); }
58
59 private:
60 friend class SecureQueue;
61 SecureQueueNode* m_next;
63 size_t m_start, m_end;
64};
65
66/*
67* Create a SecureQueue
68*/
69SecureQueue::SecureQueue() : m_bytes_read(0) {
70 set_next(nullptr, 0);
71 m_head = m_tail = new SecureQueueNode; // NOLINT(*-owning-memory)
72}
73
74/*
75* Copy a SecureQueue
76*/
77SecureQueue::SecureQueue(const SecureQueue& input) : Fanout_Filter(), m_bytes_read(0) {
78 set_next(nullptr, 0);
79
80 m_head = m_tail = new SecureQueueNode; // NOLINT(*-owning-memory)
81 SecureQueueNode* temp = input.m_head;
82 while(temp != nullptr) {
83 write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start);
84 temp = temp->m_next;
85 }
86}
87
88/*
89* Destroy this SecureQueue
90*/
91void SecureQueue::destroy() {
92 SecureQueueNode* temp = m_head;
93 while(temp != nullptr) {
94 SecureQueueNode* holder = temp->m_next;
95 delete temp; // NOLINT(*-owning-memory)
96 temp = holder;
97 }
98 m_head = m_tail = nullptr;
99}
100
101/*
102* Copy a SecureQueue
103*/
105 if(this == &input) {
106 return *this;
107 }
108
109 destroy();
110 m_bytes_read = input.get_bytes_read();
111 m_head = m_tail = new SecureQueueNode; // NOLINT(*-owning-memory)
112 SecureQueueNode* temp = input.m_head;
113 while(temp != nullptr) {
114 write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start);
115 temp = temp->m_next;
116 }
117 return (*this);
118}
119
120/*
121* Add some bytes to the queue
122*/
123void SecureQueue::write(const uint8_t input[], size_t length) {
124 if(m_head == nullptr) {
125 m_head = m_tail = new SecureQueueNode; // NOLINT(*-owning-memory)
126 }
127 while(length > 0) {
128 const size_t n = m_tail->write(input, length);
129 input += n;
130 length -= n;
131 if(length > 0) {
132 m_tail->m_next = new SecureQueueNode; // NOLINT(*-owning-memory)
133 m_tail = m_tail->m_next;
134 }
135 }
136}
137
138/*
139* Read some bytes from the queue
140*/
141size_t SecureQueue::read(uint8_t output[], size_t length) {
142 size_t got = 0;
143 while(length > 0 && m_head != nullptr) {
144 const size_t n = m_head->read(output, length);
145 output += n;
146 got += n;
147 length -= n;
148 if(m_head->size() == 0) {
149 SecureQueueNode* holder = m_head->m_next;
150 delete m_head; // NOLINT(*-owning-memory)
151 m_head = holder;
152 }
153 }
154 m_bytes_read += got;
155 return got;
156}
157
158/*
159* Read data, but do not remove it from queue
160*/
161size_t SecureQueue::peek(uint8_t output[], size_t length, size_t offset) const {
162 SecureQueueNode* current = m_head;
163
164 while(offset > 0 && current != nullptr) {
165 if(offset >= current->size()) {
166 offset -= current->size();
167 current = current->m_next;
168 } else {
169 break;
170 }
171 }
172
173 size_t got = 0;
174 while(length > 0 && current != nullptr) {
175 const size_t n = current->peek(output, length, offset);
176 offset = 0;
177 output += n;
178 got += n;
179 length -= n;
180 current = current->m_next;
181 }
182 return got;
183}
184
185/**
186* Return how many bytes have been read so far.
187*/
189 return m_bytes_read;
190}
191
192/*
193* Return how many bytes the queue holds
194*/
195size_t SecureQueue::size() const {
196 SecureQueueNode* current = m_head;
197 size_t count = 0;
198
199 while(current != nullptr) {
200 count += current->size();
201 current = current->m_next;
202 }
203 return count;
204}
205
206/*
207* Test if the queue has any data in it
208*/
210 return (size() == 0);
211}
212
213bool SecureQueue::empty() const {
214 return (size() == 0);
215}
216
217} // namespace Botan
void set_next(Filter *f[], size_t n)
Definition filter.h:156
bool end_of_data() const override
Definition secqueue.cpp:209
SecureQueue & operator=(const SecureQueue &other)
Definition secqueue.cpp:104
size_t peek(uint8_t output[], size_t length, size_t offset=0) const override
Definition secqueue.cpp:161
size_t get_bytes_read() const override
Definition secqueue.cpp:188
bool empty() const
Definition secqueue.cpp:213
size_t size() const
Definition secqueue.cpp:195
SecureQueue(SecureQueue &&other)=delete
size_t read(uint8_t output[], size_t length) override
Definition secqueue.cpp:141
void write(const uint8_t input[], size_t length) override
Definition secqueue.cpp:123
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:145
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69
constexpr size_t DefaultBufferSize
Definition types.h:137