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