1*e9778795SPeter Avalos /* $OpenBSD: sshbuf.c,v 1.6 2016/01/12 23:42:54 djm Exp $ */ 236e94dc5SPeter Avalos /* 336e94dc5SPeter Avalos * Copyright (c) 2011 Damien Miller 436e94dc5SPeter Avalos * 536e94dc5SPeter Avalos * Permission to use, copy, modify, and distribute this software for any 636e94dc5SPeter Avalos * purpose with or without fee is hereby granted, provided that the above 736e94dc5SPeter Avalos * copyright notice and this permission notice appear in all copies. 836e94dc5SPeter Avalos * 936e94dc5SPeter Avalos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1036e94dc5SPeter Avalos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1136e94dc5SPeter Avalos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1236e94dc5SPeter Avalos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1336e94dc5SPeter Avalos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1436e94dc5SPeter Avalos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1536e94dc5SPeter Avalos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1636e94dc5SPeter Avalos */ 1736e94dc5SPeter Avalos 1836e94dc5SPeter Avalos #define SSHBUF_INTERNAL 1936e94dc5SPeter Avalos #include "includes.h" 2036e94dc5SPeter Avalos 21*e9778795SPeter Avalos #include <sys/param.h> /* roundup */ 2236e94dc5SPeter Avalos #include <sys/types.h> 2336e94dc5SPeter Avalos #include <signal.h> 2436e94dc5SPeter Avalos #include <stdlib.h> 2536e94dc5SPeter Avalos #include <stdio.h> 2636e94dc5SPeter Avalos #include <string.h> 2736e94dc5SPeter Avalos 2836e94dc5SPeter Avalos #include "ssherr.h" 2936e94dc5SPeter Avalos #include "sshbuf.h" 3036e94dc5SPeter Avalos 3136e94dc5SPeter Avalos static inline int 3236e94dc5SPeter Avalos sshbuf_check_sanity(const struct sshbuf *buf) 3336e94dc5SPeter Avalos { 3436e94dc5SPeter Avalos SSHBUF_TELL("sanity"); 3536e94dc5SPeter Avalos if (__predict_false(buf == NULL || 3636e94dc5SPeter Avalos (!buf->readonly && buf->d != buf->cd) || 3736e94dc5SPeter Avalos buf->refcount < 1 || buf->refcount > SSHBUF_REFS_MAX || 3836e94dc5SPeter Avalos buf->cd == NULL || 3936e94dc5SPeter Avalos (buf->dont_free && (buf->readonly || buf->parent != NULL)) || 4036e94dc5SPeter Avalos buf->max_size > SSHBUF_SIZE_MAX || 4136e94dc5SPeter Avalos buf->alloc > buf->max_size || 4236e94dc5SPeter Avalos buf->size > buf->alloc || 4336e94dc5SPeter Avalos buf->off > buf->size)) { 4436e94dc5SPeter Avalos /* Do not try to recover from corrupted buffer internals */ 4536e94dc5SPeter Avalos SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); 4636e94dc5SPeter Avalos signal(SIGSEGV, SIG_DFL); 4736e94dc5SPeter Avalos raise(SIGSEGV); 4836e94dc5SPeter Avalos return SSH_ERR_INTERNAL_ERROR; 4936e94dc5SPeter Avalos } 5036e94dc5SPeter Avalos return 0; 5136e94dc5SPeter Avalos } 5236e94dc5SPeter Avalos 5336e94dc5SPeter Avalos static void 5436e94dc5SPeter Avalos sshbuf_maybe_pack(struct sshbuf *buf, int force) 5536e94dc5SPeter Avalos { 5636e94dc5SPeter Avalos SSHBUF_DBG(("force %d", force)); 5736e94dc5SPeter Avalos SSHBUF_TELL("pre-pack"); 5836e94dc5SPeter Avalos if (buf->off == 0 || buf->readonly || buf->refcount > 1) 5936e94dc5SPeter Avalos return; 6036e94dc5SPeter Avalos if (force || 6136e94dc5SPeter Avalos (buf->off >= SSHBUF_PACK_MIN && buf->off >= buf->size / 2)) { 6236e94dc5SPeter Avalos memmove(buf->d, buf->d + buf->off, buf->size - buf->off); 6336e94dc5SPeter Avalos buf->size -= buf->off; 6436e94dc5SPeter Avalos buf->off = 0; 6536e94dc5SPeter Avalos SSHBUF_TELL("packed"); 6636e94dc5SPeter Avalos } 6736e94dc5SPeter Avalos } 6836e94dc5SPeter Avalos 6936e94dc5SPeter Avalos struct sshbuf * 7036e94dc5SPeter Avalos sshbuf_new(void) 7136e94dc5SPeter Avalos { 7236e94dc5SPeter Avalos struct sshbuf *ret; 7336e94dc5SPeter Avalos 7436e94dc5SPeter Avalos if ((ret = calloc(sizeof(*ret), 1)) == NULL) 7536e94dc5SPeter Avalos return NULL; 7636e94dc5SPeter Avalos ret->alloc = SSHBUF_SIZE_INIT; 7736e94dc5SPeter Avalos ret->max_size = SSHBUF_SIZE_MAX; 7836e94dc5SPeter Avalos ret->readonly = 0; 7936e94dc5SPeter Avalos ret->refcount = 1; 8036e94dc5SPeter Avalos ret->parent = NULL; 8136e94dc5SPeter Avalos if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) { 8236e94dc5SPeter Avalos free(ret); 8336e94dc5SPeter Avalos return NULL; 8436e94dc5SPeter Avalos } 8536e94dc5SPeter Avalos return ret; 8636e94dc5SPeter Avalos } 8736e94dc5SPeter Avalos 8836e94dc5SPeter Avalos struct sshbuf * 8936e94dc5SPeter Avalos sshbuf_from(const void *blob, size_t len) 9036e94dc5SPeter Avalos { 9136e94dc5SPeter Avalos struct sshbuf *ret; 9236e94dc5SPeter Avalos 9336e94dc5SPeter Avalos if (blob == NULL || len > SSHBUF_SIZE_MAX || 9436e94dc5SPeter Avalos (ret = calloc(sizeof(*ret), 1)) == NULL) 9536e94dc5SPeter Avalos return NULL; 9636e94dc5SPeter Avalos ret->alloc = ret->size = ret->max_size = len; 9736e94dc5SPeter Avalos ret->readonly = 1; 9836e94dc5SPeter Avalos ret->refcount = 1; 9936e94dc5SPeter Avalos ret->parent = NULL; 10036e94dc5SPeter Avalos ret->cd = blob; 10136e94dc5SPeter Avalos ret->d = NULL; 10236e94dc5SPeter Avalos return ret; 10336e94dc5SPeter Avalos } 10436e94dc5SPeter Avalos 10536e94dc5SPeter Avalos int 10636e94dc5SPeter Avalos sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent) 10736e94dc5SPeter Avalos { 10836e94dc5SPeter Avalos int r; 10936e94dc5SPeter Avalos 11036e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(child)) != 0 || 11136e94dc5SPeter Avalos (r = sshbuf_check_sanity(parent)) != 0) 11236e94dc5SPeter Avalos return r; 11336e94dc5SPeter Avalos child->parent = parent; 11436e94dc5SPeter Avalos child->parent->refcount++; 11536e94dc5SPeter Avalos return 0; 11636e94dc5SPeter Avalos } 11736e94dc5SPeter Avalos 11836e94dc5SPeter Avalos struct sshbuf * 11936e94dc5SPeter Avalos sshbuf_fromb(struct sshbuf *buf) 12036e94dc5SPeter Avalos { 12136e94dc5SPeter Avalos struct sshbuf *ret; 12236e94dc5SPeter Avalos 12336e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0) 12436e94dc5SPeter Avalos return NULL; 12536e94dc5SPeter Avalos if ((ret = sshbuf_from(sshbuf_ptr(buf), sshbuf_len(buf))) == NULL) 12636e94dc5SPeter Avalos return NULL; 12736e94dc5SPeter Avalos if (sshbuf_set_parent(ret, buf) != 0) { 12836e94dc5SPeter Avalos sshbuf_free(ret); 12936e94dc5SPeter Avalos return NULL; 13036e94dc5SPeter Avalos } 13136e94dc5SPeter Avalos return ret; 13236e94dc5SPeter Avalos } 13336e94dc5SPeter Avalos 13436e94dc5SPeter Avalos void 13536e94dc5SPeter Avalos sshbuf_init(struct sshbuf *ret) 13636e94dc5SPeter Avalos { 137*e9778795SPeter Avalos explicit_bzero(ret, sizeof(*ret)); 13836e94dc5SPeter Avalos ret->alloc = SSHBUF_SIZE_INIT; 13936e94dc5SPeter Avalos ret->max_size = SSHBUF_SIZE_MAX; 14036e94dc5SPeter Avalos ret->readonly = 0; 14136e94dc5SPeter Avalos ret->dont_free = 1; 14236e94dc5SPeter Avalos ret->refcount = 1; 14336e94dc5SPeter Avalos if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) 14436e94dc5SPeter Avalos ret->alloc = 0; 14536e94dc5SPeter Avalos } 14636e94dc5SPeter Avalos 14736e94dc5SPeter Avalos void 14836e94dc5SPeter Avalos sshbuf_free(struct sshbuf *buf) 14936e94dc5SPeter Avalos { 15036e94dc5SPeter Avalos int dont_free = 0; 15136e94dc5SPeter Avalos 15236e94dc5SPeter Avalos if (buf == NULL) 15336e94dc5SPeter Avalos return; 15436e94dc5SPeter Avalos /* 15536e94dc5SPeter Avalos * The following will leak on insane buffers, but this is the safest 15636e94dc5SPeter Avalos * course of action - an invalid pointer or already-freed pointer may 15736e94dc5SPeter Avalos * have been passed to us and continuing to scribble over memory would 15836e94dc5SPeter Avalos * be bad. 15936e94dc5SPeter Avalos */ 16036e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0) 16136e94dc5SPeter Avalos return; 16236e94dc5SPeter Avalos /* 16336e94dc5SPeter Avalos * If we are a child, the free our parent to decrement its reference 16436e94dc5SPeter Avalos * count and possibly free it. 16536e94dc5SPeter Avalos */ 16636e94dc5SPeter Avalos sshbuf_free(buf->parent); 16736e94dc5SPeter Avalos buf->parent = NULL; 16836e94dc5SPeter Avalos /* 16936e94dc5SPeter Avalos * If we are a parent with still-extant children, then don't free just 17036e94dc5SPeter Avalos * yet. The last child's call to sshbuf_free should decrement our 17136e94dc5SPeter Avalos * refcount to 0 and trigger the actual free. 17236e94dc5SPeter Avalos */ 17336e94dc5SPeter Avalos buf->refcount--; 17436e94dc5SPeter Avalos if (buf->refcount > 0) 17536e94dc5SPeter Avalos return; 17636e94dc5SPeter Avalos dont_free = buf->dont_free; 17736e94dc5SPeter Avalos if (!buf->readonly) { 178*e9778795SPeter Avalos explicit_bzero(buf->d, buf->alloc); 17936e94dc5SPeter Avalos free(buf->d); 18036e94dc5SPeter Avalos } 181*e9778795SPeter Avalos explicit_bzero(buf, sizeof(*buf)); 18236e94dc5SPeter Avalos if (!dont_free) 18336e94dc5SPeter Avalos free(buf); 18436e94dc5SPeter Avalos } 18536e94dc5SPeter Avalos 18636e94dc5SPeter Avalos void 18736e94dc5SPeter Avalos sshbuf_reset(struct sshbuf *buf) 18836e94dc5SPeter Avalos { 18936e94dc5SPeter Avalos u_char *d; 19036e94dc5SPeter Avalos 19136e94dc5SPeter Avalos if (buf->readonly || buf->refcount > 1) { 19236e94dc5SPeter Avalos /* Nonsensical. Just make buffer appear empty */ 19336e94dc5SPeter Avalos buf->off = buf->size; 19436e94dc5SPeter Avalos return; 19536e94dc5SPeter Avalos } 19636e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) == 0) 197*e9778795SPeter Avalos explicit_bzero(buf->d, buf->alloc); 19836e94dc5SPeter Avalos buf->off = buf->size = 0; 19936e94dc5SPeter Avalos if (buf->alloc != SSHBUF_SIZE_INIT) { 20036e94dc5SPeter Avalos if ((d = realloc(buf->d, SSHBUF_SIZE_INIT)) != NULL) { 20136e94dc5SPeter Avalos buf->cd = buf->d = d; 20236e94dc5SPeter Avalos buf->alloc = SSHBUF_SIZE_INIT; 20336e94dc5SPeter Avalos } 20436e94dc5SPeter Avalos } 20536e94dc5SPeter Avalos } 20636e94dc5SPeter Avalos 20736e94dc5SPeter Avalos size_t 20836e94dc5SPeter Avalos sshbuf_max_size(const struct sshbuf *buf) 20936e94dc5SPeter Avalos { 21036e94dc5SPeter Avalos return buf->max_size; 21136e94dc5SPeter Avalos } 21236e94dc5SPeter Avalos 21336e94dc5SPeter Avalos size_t 21436e94dc5SPeter Avalos sshbuf_alloc(const struct sshbuf *buf) 21536e94dc5SPeter Avalos { 21636e94dc5SPeter Avalos return buf->alloc; 21736e94dc5SPeter Avalos } 21836e94dc5SPeter Avalos 21936e94dc5SPeter Avalos const struct sshbuf * 22036e94dc5SPeter Avalos sshbuf_parent(const struct sshbuf *buf) 22136e94dc5SPeter Avalos { 22236e94dc5SPeter Avalos return buf->parent; 22336e94dc5SPeter Avalos } 22436e94dc5SPeter Avalos 22536e94dc5SPeter Avalos u_int 22636e94dc5SPeter Avalos sshbuf_refcount(const struct sshbuf *buf) 22736e94dc5SPeter Avalos { 22836e94dc5SPeter Avalos return buf->refcount; 22936e94dc5SPeter Avalos } 23036e94dc5SPeter Avalos 23136e94dc5SPeter Avalos int 23236e94dc5SPeter Avalos sshbuf_set_max_size(struct sshbuf *buf, size_t max_size) 23336e94dc5SPeter Avalos { 23436e94dc5SPeter Avalos size_t rlen; 23536e94dc5SPeter Avalos u_char *dp; 23636e94dc5SPeter Avalos int r; 23736e94dc5SPeter Avalos 23836e94dc5SPeter Avalos SSHBUF_DBG(("set max buf = %p len = %zu", buf, max_size)); 23936e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(buf)) != 0) 24036e94dc5SPeter Avalos return r; 24136e94dc5SPeter Avalos if (max_size == buf->max_size) 24236e94dc5SPeter Avalos return 0; 24336e94dc5SPeter Avalos if (buf->readonly || buf->refcount > 1) 24436e94dc5SPeter Avalos return SSH_ERR_BUFFER_READ_ONLY; 24536e94dc5SPeter Avalos if (max_size > SSHBUF_SIZE_MAX) 24636e94dc5SPeter Avalos return SSH_ERR_NO_BUFFER_SPACE; 24736e94dc5SPeter Avalos /* pack and realloc if necessary */ 24836e94dc5SPeter Avalos sshbuf_maybe_pack(buf, max_size < buf->size); 24936e94dc5SPeter Avalos if (max_size < buf->alloc && max_size > buf->size) { 25036e94dc5SPeter Avalos if (buf->size < SSHBUF_SIZE_INIT) 25136e94dc5SPeter Avalos rlen = SSHBUF_SIZE_INIT; 25236e94dc5SPeter Avalos else 25336e94dc5SPeter Avalos rlen = roundup(buf->size, SSHBUF_SIZE_INC); 25436e94dc5SPeter Avalos if (rlen > max_size) 25536e94dc5SPeter Avalos rlen = max_size; 256*e9778795SPeter Avalos explicit_bzero(buf->d + buf->size, buf->alloc - buf->size); 25736e94dc5SPeter Avalos SSHBUF_DBG(("new alloc = %zu", rlen)); 25836e94dc5SPeter Avalos if ((dp = realloc(buf->d, rlen)) == NULL) 25936e94dc5SPeter Avalos return SSH_ERR_ALLOC_FAIL; 26036e94dc5SPeter Avalos buf->cd = buf->d = dp; 26136e94dc5SPeter Avalos buf->alloc = rlen; 26236e94dc5SPeter Avalos } 26336e94dc5SPeter Avalos SSHBUF_TELL("new-max"); 26436e94dc5SPeter Avalos if (max_size < buf->alloc) 26536e94dc5SPeter Avalos return SSH_ERR_NO_BUFFER_SPACE; 26636e94dc5SPeter Avalos buf->max_size = max_size; 26736e94dc5SPeter Avalos return 0; 26836e94dc5SPeter Avalos } 26936e94dc5SPeter Avalos 27036e94dc5SPeter Avalos size_t 27136e94dc5SPeter Avalos sshbuf_len(const struct sshbuf *buf) 27236e94dc5SPeter Avalos { 27336e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0) 27436e94dc5SPeter Avalos return 0; 27536e94dc5SPeter Avalos return buf->size - buf->off; 27636e94dc5SPeter Avalos } 27736e94dc5SPeter Avalos 27836e94dc5SPeter Avalos size_t 27936e94dc5SPeter Avalos sshbuf_avail(const struct sshbuf *buf) 28036e94dc5SPeter Avalos { 28136e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) 28236e94dc5SPeter Avalos return 0; 28336e94dc5SPeter Avalos return buf->max_size - (buf->size - buf->off); 28436e94dc5SPeter Avalos } 28536e94dc5SPeter Avalos 28636e94dc5SPeter Avalos const u_char * 28736e94dc5SPeter Avalos sshbuf_ptr(const struct sshbuf *buf) 28836e94dc5SPeter Avalos { 28936e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0) 29036e94dc5SPeter Avalos return NULL; 29136e94dc5SPeter Avalos return buf->cd + buf->off; 29236e94dc5SPeter Avalos } 29336e94dc5SPeter Avalos 29436e94dc5SPeter Avalos u_char * 29536e94dc5SPeter Avalos sshbuf_mutable_ptr(const struct sshbuf *buf) 29636e94dc5SPeter Avalos { 29736e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) 29836e94dc5SPeter Avalos return NULL; 29936e94dc5SPeter Avalos return buf->d + buf->off; 30036e94dc5SPeter Avalos } 30136e94dc5SPeter Avalos 30236e94dc5SPeter Avalos int 30336e94dc5SPeter Avalos sshbuf_check_reserve(const struct sshbuf *buf, size_t len) 30436e94dc5SPeter Avalos { 30536e94dc5SPeter Avalos int r; 30636e94dc5SPeter Avalos 30736e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(buf)) != 0) 30836e94dc5SPeter Avalos return r; 30936e94dc5SPeter Avalos if (buf->readonly || buf->refcount > 1) 31036e94dc5SPeter Avalos return SSH_ERR_BUFFER_READ_ONLY; 31136e94dc5SPeter Avalos SSHBUF_TELL("check"); 31236e94dc5SPeter Avalos /* Check that len is reasonable and that max_size + available < len */ 31336e94dc5SPeter Avalos if (len > buf->max_size || buf->max_size - len < buf->size - buf->off) 31436e94dc5SPeter Avalos return SSH_ERR_NO_BUFFER_SPACE; 31536e94dc5SPeter Avalos return 0; 31636e94dc5SPeter Avalos } 31736e94dc5SPeter Avalos 31836e94dc5SPeter Avalos int 31936e94dc5SPeter Avalos sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp) 32036e94dc5SPeter Avalos { 32136e94dc5SPeter Avalos size_t rlen, need; 32236e94dc5SPeter Avalos u_char *dp; 32336e94dc5SPeter Avalos int r; 32436e94dc5SPeter Avalos 32536e94dc5SPeter Avalos if (dpp != NULL) 32636e94dc5SPeter Avalos *dpp = NULL; 32736e94dc5SPeter Avalos 32836e94dc5SPeter Avalos SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len)); 32936e94dc5SPeter Avalos if ((r = sshbuf_check_reserve(buf, len)) != 0) 33036e94dc5SPeter Avalos return r; 33136e94dc5SPeter Avalos /* 33236e94dc5SPeter Avalos * If the requested allocation appended would push us past max_size 33336e94dc5SPeter Avalos * then pack the buffer, zeroing buf->off. 33436e94dc5SPeter Avalos */ 33536e94dc5SPeter Avalos sshbuf_maybe_pack(buf, buf->size + len > buf->max_size); 33636e94dc5SPeter Avalos SSHBUF_TELL("reserve"); 33736e94dc5SPeter Avalos if (len + buf->size > buf->alloc) { 33836e94dc5SPeter Avalos /* 33936e94dc5SPeter Avalos * Prefer to alloc in SSHBUF_SIZE_INC units, but 34036e94dc5SPeter Avalos * allocate less if doing so would overflow max_size. 34136e94dc5SPeter Avalos */ 34236e94dc5SPeter Avalos need = len + buf->size - buf->alloc; 34336e94dc5SPeter Avalos rlen = roundup(buf->alloc + need, SSHBUF_SIZE_INC); 34436e94dc5SPeter Avalos SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen)); 34536e94dc5SPeter Avalos if (rlen > buf->max_size) 34636e94dc5SPeter Avalos rlen = buf->alloc + need; 34736e94dc5SPeter Avalos SSHBUF_DBG(("adjusted rlen %zu", rlen)); 34836e94dc5SPeter Avalos if ((dp = realloc(buf->d, rlen)) == NULL) { 34936e94dc5SPeter Avalos SSHBUF_DBG(("realloc fail")); 35036e94dc5SPeter Avalos if (dpp != NULL) 35136e94dc5SPeter Avalos *dpp = NULL; 35236e94dc5SPeter Avalos return SSH_ERR_ALLOC_FAIL; 35336e94dc5SPeter Avalos } 35436e94dc5SPeter Avalos buf->alloc = rlen; 35536e94dc5SPeter Avalos buf->cd = buf->d = dp; 35636e94dc5SPeter Avalos if ((r = sshbuf_check_reserve(buf, len)) < 0) { 35736e94dc5SPeter Avalos /* shouldn't fail */ 35836e94dc5SPeter Avalos if (dpp != NULL) 35936e94dc5SPeter Avalos *dpp = NULL; 36036e94dc5SPeter Avalos return r; 36136e94dc5SPeter Avalos } 36236e94dc5SPeter Avalos } 36336e94dc5SPeter Avalos dp = buf->d + buf->size; 36436e94dc5SPeter Avalos buf->size += len; 36536e94dc5SPeter Avalos SSHBUF_TELL("done"); 36636e94dc5SPeter Avalos if (dpp != NULL) 36736e94dc5SPeter Avalos *dpp = dp; 36836e94dc5SPeter Avalos return 0; 36936e94dc5SPeter Avalos } 37036e94dc5SPeter Avalos 37136e94dc5SPeter Avalos int 37236e94dc5SPeter Avalos sshbuf_consume(struct sshbuf *buf, size_t len) 37336e94dc5SPeter Avalos { 37436e94dc5SPeter Avalos int r; 37536e94dc5SPeter Avalos 37636e94dc5SPeter Avalos SSHBUF_DBG(("len = %zu", len)); 37736e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(buf)) != 0) 37836e94dc5SPeter Avalos return r; 37936e94dc5SPeter Avalos if (len == 0) 38036e94dc5SPeter Avalos return 0; 38136e94dc5SPeter Avalos if (len > sshbuf_len(buf)) 38236e94dc5SPeter Avalos return SSH_ERR_MESSAGE_INCOMPLETE; 38336e94dc5SPeter Avalos buf->off += len; 38436e94dc5SPeter Avalos SSHBUF_TELL("done"); 38536e94dc5SPeter Avalos return 0; 38636e94dc5SPeter Avalos } 38736e94dc5SPeter Avalos 38836e94dc5SPeter Avalos int 38936e94dc5SPeter Avalos sshbuf_consume_end(struct sshbuf *buf, size_t len) 39036e94dc5SPeter Avalos { 39136e94dc5SPeter Avalos int r; 39236e94dc5SPeter Avalos 39336e94dc5SPeter Avalos SSHBUF_DBG(("len = %zu", len)); 39436e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(buf)) != 0) 39536e94dc5SPeter Avalos return r; 39636e94dc5SPeter Avalos if (len == 0) 39736e94dc5SPeter Avalos return 0; 39836e94dc5SPeter Avalos if (len > sshbuf_len(buf)) 39936e94dc5SPeter Avalos return SSH_ERR_MESSAGE_INCOMPLETE; 40036e94dc5SPeter Avalos buf->size -= len; 40136e94dc5SPeter Avalos SSHBUF_TELL("done"); 40236e94dc5SPeter Avalos return 0; 40336e94dc5SPeter Avalos } 40436e94dc5SPeter Avalos 405