--- /dev/null
+#define _POSIX_C_SOURCE 200809L
+
+#include <string.h>
+#include <errno.h>
+
+#include "tlse.h"
+#include "buffer.h"
+
+void tls_buffer_init(struct tls_buffer *buffer, size_t initial) {
+ buffer->buffer = 0;
+ buffer->len = 0;
+ buffer->size = 0;
+ buffer->error = 0;
+ if (initial) {
+ errno = 0;
+ buffer->buffer = malloc(initial);
+ if (buffer->buffer) {
+ memset(buffer->buffer, 0, initial);
+ buffer->size = initial;
+ } else {
+ buffer->error = errno;
+ }
+ }
+}
+
+void tls_buffer_compact(struct tls_buffer *b) {
+ void *new;
+
+ if (b->error || b->size == b->len) {
+ return;
+ }
+
+ errno = 0;
+ new = realloc(b->buffer, b->len);
+
+ if (new == NULL) {
+ b->error = errno;
+ return;
+ }
+
+ b->buffer = new;
+ return;
+}
+
+/* makes sure there's at least need bytes free */
+void tls_buffer_expand(struct tls_buffer *buf, size_t need) {
+ size_t want;
+
+ if (buf->error) {
+ return;
+ }
+
+ want = buf->len + need;
+
+ if (want <= buf->size) {
+ return;
+ }
+
+ errno = 0;
+ char *new = realloc(buf->buffer, want);
+ if (new) {
+ buf->buffer = new;
+ buf->size = want;
+ memset(buf->buffer + buf->len, 0, buf->size - buf->len);
+ } else {
+ buf->error = errno;
+ }
+}
+
+void tls_buffer_free(struct tls_buffer *buffer) {
+ /* TODO only zero out memory if it's "secure" buffer */
+ if (buffer->buffer && buffer->len) {
+ memset(buffer->buffer, 0, buffer->len);
+ }
+ free(buffer->buffer);
+ tls_buffer_init(buffer, 0);
+}
+
+void tls_buffer_set(struct tls_buffer *buffer, int ch) {
+ /* TODO only zero out memory if it's "secure" buffer */
+ if (buffer->buffer && buffer->size) {
+ memset(buffer->buffer, ch, buffer->size);
+ }
+}
+
+void tls_buffer_append(struct tls_buffer *buffer, const unsigned char *bytes, size_t n) {
+ tls_buffer_expand(buffer, n);
+
+ if (buffer->error || !bytes) {
+ return;
+ }
+
+ memcpy(buffer->buffer + buffer->len, bytes, n);
+ buffer->len += n;
+}
+
+void tls_buffer_append16(struct tls_buffer *buffer, uint16_t n) {
+ tls_buffer_expand(buffer, 2);
+
+ if (buffer->error) {
+ return;
+ }
+
+ buffer->buffer[buffer->len++] = (n >> 8) & 0xff;
+ buffer->buffer[buffer->len++] = n & 0xff;
+}
+
+void tls_buffer_append24(struct tls_buffer *buffer, uint32_t n) {
+ tls_buffer_expand(buffer, 3);
+
+ if (buffer->error) {
+ return;
+ }
+
+ buffer->buffer[buffer->len++] = (n >> 16) & 0xff;
+ buffer->buffer[buffer->len++] = (n >> 8) & 0xff;
+ buffer->buffer[buffer->len++] = n & 0xff;
+}
+
+void tls_buffer_append_byte(struct tls_buffer *buffer, uint8_t n) {
+ tls_buffer_expand(buffer, 1);
+
+ if (buffer->error) {
+ return;
+ }
+
+ buffer->buffer[buffer->len++] = n & 0xff;
+}
+
+void tls_buffer_write16(struct tls_buffer *buffer, uint16_t n, size_t at) {
+ if (at+2 > buffer->size) {
+ tls_buffer_expand(buffer, at+2 - buffer->size);
+ }
+
+ if (buffer->error) {
+ return;
+ }
+
+ buffer->buffer[at] = (n >> 8) & 0xff;
+ buffer->buffer[at+1] = n & 0xff;
+
+ if (at+2 > buffer->len) {
+ buffer->len = at + 2;
+ }
+}
+
+uint16_t tls_buffer_read16(struct tls_buffer *buffer, size_t at) {
+ uint16_t res = 0;
+
+ if (buffer->error || at+2 < buffer->len) {
+ return 0;
+ }
+
+ res = (buffer->buffer[at] << 8) + buffer->buffer[at+1];
+ return res;
+}
+
+uint64_t tls_buffer_readbe(struct tls_buffer *buffer, int bytes, size_t at) {
+ uint16_t res = 0;
+ int i;
+
+ if (buffer->error || at+bytes < buffer->len) {
+ return 0;
+ }
+
+ for (i=0; i<bytes; i++) {
+ res <<= 8;
+ res += buffer->buffer[at+i];
+ }
+
+ return res;
+}
+
+void tls_buffer_writebe(struct tls_buffer *buffer, int bytes, size_t at, uint64_t val) {
+ int i;
+ if (at+bytes > buffer->size) {
+ tls_buffer_expand(buffer, at+bytes - buffer->size);
+ }
+
+ if (buffer->error) {
+ return;
+ }
+
+ for (i=bytes-1; i>=0; i--) {
+ buffer->buffer[at+i] = val & 0xff;
+ val >>= 8;
+ }
+
+ return;
+}
+
+
+void tls_buffer_shift(struct tls_buffer *buffer, size_t n) {
+ if (buffer->error) {
+ return;
+ }
+
+ if (buffer->len < n) {
+ n = buffer->len;
+ }
+
+ if (n) {
+ memmove(buffer->buffer, buffer->buffer + n, buffer->len - n);
+ memset(buffer->buffer + buffer->len - n, 0, n);
+#if 0
+ fprintf(stderr, "memmove(%p, %p, %zu)\n", buffer->buffer,
+ buffer->buffer+n, buffer->len - n);
+ fprintf(stderr, "memset(%p, %d, %zu)\n", buffer->buffer+n,
+ 0, n);
+#endif
+
+ buffer->len -= n;
+ }
+}
+
+/* make room at the beginning */
+void tls_buffer_unshift(struct tls_buffer *buffer, size_t n) {
+ tls_buffer_expand(buffer, n);
+
+ if (buffer->error) {
+ return;
+ }
+
+ memmove(buffer->buffer + n, buffer->buffer, n);
+ memset(buffer->buffer, 0, n);
+}
+
+#if 0
+uint32_t tls_buffer_next3(struct tls_buffer_reader *rb) {
+ uint32_t r;
+
+ r = tls_buffer_readbe(rb, 3, rb->cursor);
+ rb->cursor += 3;
+ return r;
+}
+
+uint16_t tls_buffer_next2(struct tls_buffer_reader *rb) {
+ uint16_t r;
+
+ r = tls_buffer_readbe(rb, 2, rb->cursor);
+ rb->cursor += 2;
+ return r;
+}
+
+uint8_t tls_buffer_next(struct tls_buffer_reader *rb) {
+ uint16_t r;
+
+ r = tls_buffer_readbe(rb, 2, rb->cursor);
+ rb->cursor += 2;
+
+}
+
+void tls_buffer_nextn(struct tls_buffer_reader *rb, unsigned char *b, size_t n) {
+ tls_buffer_read(rb, b, n, rb->cursor);
+ rb->cursor += n;
+}
+#endif