1 /* $OpenBSD: tls_buffer.c,v 1.1 2021/10/23 13:12:14 jsing Exp $ */ 2 /* 3 * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <stdlib.h> 19 #include <string.h> 20 21 #include "bytestring.h" 22 #include "tls_internal.h" 23 24 struct tls_buffer { 25 size_t capacity; 26 uint8_t *data; 27 size_t len; 28 size_t offset; 29 }; 30 31 static int tls_buffer_resize(struct tls_buffer *buf, size_t capacity); 32 33 struct tls_buffer * 34 tls_buffer_new(size_t init_size) 35 { 36 struct tls_buffer *buf = NULL; 37 38 if ((buf = calloc(1, sizeof(struct tls_buffer))) == NULL) 39 goto err; 40 41 if (!tls_buffer_resize(buf, init_size)) 42 goto err; 43 44 return buf; 45 46 err: 47 tls_buffer_free(buf); 48 49 return NULL; 50 } 51 52 void 53 tls_buffer_free(struct tls_buffer *buf) 54 { 55 if (buf == NULL) 56 return; 57 58 freezero(buf->data, buf->capacity); 59 freezero(buf, sizeof(struct tls_buffer)); 60 } 61 62 static int 63 tls_buffer_resize(struct tls_buffer *buf, size_t capacity) 64 { 65 uint8_t *data; 66 67 if (buf->capacity == capacity) 68 return 1; 69 70 if ((data = recallocarray(buf->data, buf->capacity, capacity, 1)) == NULL) 71 return 0; 72 73 buf->data = data; 74 buf->capacity = capacity; 75 76 return 1; 77 } 78 79 int 80 tls_buffer_set_data(struct tls_buffer *buf, CBS *data) 81 { 82 if (!tls_buffer_resize(buf, CBS_len(data))) 83 return 0; 84 memcpy(buf->data, CBS_data(data), CBS_len(data)); 85 return 1; 86 } 87 88 ssize_t 89 tls_buffer_extend(struct tls_buffer *buf, size_t len, 90 tls_read_cb read_cb, void *cb_arg) 91 { 92 ssize_t ret; 93 94 if (len == buf->len) 95 return buf->len; 96 97 if (len < buf->len) 98 return TLS_IO_FAILURE; 99 100 if (!tls_buffer_resize(buf, len)) 101 return TLS_IO_FAILURE; 102 103 for (;;) { 104 if ((ret = read_cb(&buf->data[buf->len], 105 buf->capacity - buf->len, cb_arg)) <= 0) 106 return ret; 107 108 if (ret > buf->capacity - buf->len) 109 return TLS_IO_FAILURE; 110 111 buf->len += ret; 112 113 if (buf->len == buf->capacity) 114 return buf->len; 115 } 116 } 117 118 void 119 tls_buffer_cbs(struct tls_buffer *buf, CBS *cbs) 120 { 121 CBS_init(cbs, buf->data, buf->len); 122 } 123 124 int 125 tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len) 126 { 127 if (out == NULL || out_len == NULL) 128 return 0; 129 130 *out = buf->data; 131 *out_len = buf->len; 132 133 buf->capacity = 0; 134 buf->data = NULL; 135 buf->len = 0; 136 137 return 1; 138 } 139