1*36e94dc5SPeter Avalos /* $OpenBSD: sshbuf.c,v 1.2 2014/06/25 14:16:09 deraadt Exp $ */ 2*36e94dc5SPeter Avalos /* 3*36e94dc5SPeter Avalos * Copyright (c) 2011 Damien Miller 4*36e94dc5SPeter Avalos * 5*36e94dc5SPeter Avalos * Permission to use, copy, modify, and distribute this software for any 6*36e94dc5SPeter Avalos * purpose with or without fee is hereby granted, provided that the above 7*36e94dc5SPeter Avalos * copyright notice and this permission notice appear in all copies. 8*36e94dc5SPeter Avalos * 9*36e94dc5SPeter Avalos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*36e94dc5SPeter Avalos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*36e94dc5SPeter Avalos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*36e94dc5SPeter Avalos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*36e94dc5SPeter Avalos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*36e94dc5SPeter Avalos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*36e94dc5SPeter Avalos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*36e94dc5SPeter Avalos */ 17*36e94dc5SPeter Avalos 18*36e94dc5SPeter Avalos #define SSHBUF_INTERNAL 19*36e94dc5SPeter Avalos #include "includes.h" 20*36e94dc5SPeter Avalos 21*36e94dc5SPeter Avalos #include <sys/types.h> 22*36e94dc5SPeter Avalos #include <sys/param.h> 23*36e94dc5SPeter Avalos #include <signal.h> 24*36e94dc5SPeter Avalos #include <stdlib.h> 25*36e94dc5SPeter Avalos #include <stdio.h> 26*36e94dc5SPeter Avalos #include <string.h> 27*36e94dc5SPeter Avalos 28*36e94dc5SPeter Avalos #include "ssherr.h" 29*36e94dc5SPeter Avalos #include "sshbuf.h" 30*36e94dc5SPeter Avalos 31*36e94dc5SPeter Avalos static inline int 32*36e94dc5SPeter Avalos sshbuf_check_sanity(const struct sshbuf *buf) 33*36e94dc5SPeter Avalos { 34*36e94dc5SPeter Avalos SSHBUF_TELL("sanity"); 35*36e94dc5SPeter Avalos if (__predict_false(buf == NULL || 36*36e94dc5SPeter Avalos (!buf->readonly && buf->d != buf->cd) || 37*36e94dc5SPeter Avalos buf->refcount < 1 || buf->refcount > SSHBUF_REFS_MAX || 38*36e94dc5SPeter Avalos buf->cd == NULL || 39*36e94dc5SPeter Avalos (buf->dont_free && (buf->readonly || buf->parent != NULL)) || 40*36e94dc5SPeter Avalos buf->max_size > SSHBUF_SIZE_MAX || 41*36e94dc5SPeter Avalos buf->alloc > buf->max_size || 42*36e94dc5SPeter Avalos buf->size > buf->alloc || 43*36e94dc5SPeter Avalos buf->off > buf->size)) { 44*36e94dc5SPeter Avalos /* Do not try to recover from corrupted buffer internals */ 45*36e94dc5SPeter Avalos SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); 46*36e94dc5SPeter Avalos signal(SIGSEGV, SIG_DFL); 47*36e94dc5SPeter Avalos raise(SIGSEGV); 48*36e94dc5SPeter Avalos return SSH_ERR_INTERNAL_ERROR; 49*36e94dc5SPeter Avalos } 50*36e94dc5SPeter Avalos return 0; 51*36e94dc5SPeter Avalos } 52*36e94dc5SPeter Avalos 53*36e94dc5SPeter Avalos static void 54*36e94dc5SPeter Avalos sshbuf_maybe_pack(struct sshbuf *buf, int force) 55*36e94dc5SPeter Avalos { 56*36e94dc5SPeter Avalos SSHBUF_DBG(("force %d", force)); 57*36e94dc5SPeter Avalos SSHBUF_TELL("pre-pack"); 58*36e94dc5SPeter Avalos if (buf->off == 0 || buf->readonly || buf->refcount > 1) 59*36e94dc5SPeter Avalos return; 60*36e94dc5SPeter Avalos if (force || 61*36e94dc5SPeter Avalos (buf->off >= SSHBUF_PACK_MIN && buf->off >= buf->size / 2)) { 62*36e94dc5SPeter Avalos memmove(buf->d, buf->d + buf->off, buf->size - buf->off); 63*36e94dc5SPeter Avalos buf->size -= buf->off; 64*36e94dc5SPeter Avalos buf->off = 0; 65*36e94dc5SPeter Avalos SSHBUF_TELL("packed"); 66*36e94dc5SPeter Avalos } 67*36e94dc5SPeter Avalos } 68*36e94dc5SPeter Avalos 69*36e94dc5SPeter Avalos struct sshbuf * 70*36e94dc5SPeter Avalos sshbuf_new(void) 71*36e94dc5SPeter Avalos { 72*36e94dc5SPeter Avalos struct sshbuf *ret; 73*36e94dc5SPeter Avalos 74*36e94dc5SPeter Avalos if ((ret = calloc(sizeof(*ret), 1)) == NULL) 75*36e94dc5SPeter Avalos return NULL; 76*36e94dc5SPeter Avalos ret->alloc = SSHBUF_SIZE_INIT; 77*36e94dc5SPeter Avalos ret->max_size = SSHBUF_SIZE_MAX; 78*36e94dc5SPeter Avalos ret->readonly = 0; 79*36e94dc5SPeter Avalos ret->refcount = 1; 80*36e94dc5SPeter Avalos ret->parent = NULL; 81*36e94dc5SPeter Avalos if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) { 82*36e94dc5SPeter Avalos free(ret); 83*36e94dc5SPeter Avalos return NULL; 84*36e94dc5SPeter Avalos } 85*36e94dc5SPeter Avalos return ret; 86*36e94dc5SPeter Avalos } 87*36e94dc5SPeter Avalos 88*36e94dc5SPeter Avalos struct sshbuf * 89*36e94dc5SPeter Avalos sshbuf_from(const void *blob, size_t len) 90*36e94dc5SPeter Avalos { 91*36e94dc5SPeter Avalos struct sshbuf *ret; 92*36e94dc5SPeter Avalos 93*36e94dc5SPeter Avalos if (blob == NULL || len > SSHBUF_SIZE_MAX || 94*36e94dc5SPeter Avalos (ret = calloc(sizeof(*ret), 1)) == NULL) 95*36e94dc5SPeter Avalos return NULL; 96*36e94dc5SPeter Avalos ret->alloc = ret->size = ret->max_size = len; 97*36e94dc5SPeter Avalos ret->readonly = 1; 98*36e94dc5SPeter Avalos ret->refcount = 1; 99*36e94dc5SPeter Avalos ret->parent = NULL; 100*36e94dc5SPeter Avalos ret->cd = blob; 101*36e94dc5SPeter Avalos ret->d = NULL; 102*36e94dc5SPeter Avalos return ret; 103*36e94dc5SPeter Avalos } 104*36e94dc5SPeter Avalos 105*36e94dc5SPeter Avalos int 106*36e94dc5SPeter Avalos sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent) 107*36e94dc5SPeter Avalos { 108*36e94dc5SPeter Avalos int r; 109*36e94dc5SPeter Avalos 110*36e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(child)) != 0 || 111*36e94dc5SPeter Avalos (r = sshbuf_check_sanity(parent)) != 0) 112*36e94dc5SPeter Avalos return r; 113*36e94dc5SPeter Avalos child->parent = parent; 114*36e94dc5SPeter Avalos child->parent->refcount++; 115*36e94dc5SPeter Avalos return 0; 116*36e94dc5SPeter Avalos } 117*36e94dc5SPeter Avalos 118*36e94dc5SPeter Avalos struct sshbuf * 119*36e94dc5SPeter Avalos sshbuf_fromb(struct sshbuf *buf) 120*36e94dc5SPeter Avalos { 121*36e94dc5SPeter Avalos struct sshbuf *ret; 122*36e94dc5SPeter Avalos 123*36e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0) 124*36e94dc5SPeter Avalos return NULL; 125*36e94dc5SPeter Avalos if ((ret = sshbuf_from(sshbuf_ptr(buf), sshbuf_len(buf))) == NULL) 126*36e94dc5SPeter Avalos return NULL; 127*36e94dc5SPeter Avalos if (sshbuf_set_parent(ret, buf) != 0) { 128*36e94dc5SPeter Avalos sshbuf_free(ret); 129*36e94dc5SPeter Avalos return NULL; 130*36e94dc5SPeter Avalos } 131*36e94dc5SPeter Avalos return ret; 132*36e94dc5SPeter Avalos } 133*36e94dc5SPeter Avalos 134*36e94dc5SPeter Avalos void 135*36e94dc5SPeter Avalos sshbuf_init(struct sshbuf *ret) 136*36e94dc5SPeter Avalos { 137*36e94dc5SPeter Avalos bzero(ret, sizeof(*ret)); 138*36e94dc5SPeter Avalos ret->alloc = SSHBUF_SIZE_INIT; 139*36e94dc5SPeter Avalos ret->max_size = SSHBUF_SIZE_MAX; 140*36e94dc5SPeter Avalos ret->readonly = 0; 141*36e94dc5SPeter Avalos ret->dont_free = 1; 142*36e94dc5SPeter Avalos ret->refcount = 1; 143*36e94dc5SPeter Avalos if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) 144*36e94dc5SPeter Avalos ret->alloc = 0; 145*36e94dc5SPeter Avalos } 146*36e94dc5SPeter Avalos 147*36e94dc5SPeter Avalos void 148*36e94dc5SPeter Avalos sshbuf_free(struct sshbuf *buf) 149*36e94dc5SPeter Avalos { 150*36e94dc5SPeter Avalos int dont_free = 0; 151*36e94dc5SPeter Avalos 152*36e94dc5SPeter Avalos if (buf == NULL) 153*36e94dc5SPeter Avalos return; 154*36e94dc5SPeter Avalos /* 155*36e94dc5SPeter Avalos * The following will leak on insane buffers, but this is the safest 156*36e94dc5SPeter Avalos * course of action - an invalid pointer or already-freed pointer may 157*36e94dc5SPeter Avalos * have been passed to us and continuing to scribble over memory would 158*36e94dc5SPeter Avalos * be bad. 159*36e94dc5SPeter Avalos */ 160*36e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0) 161*36e94dc5SPeter Avalos return; 162*36e94dc5SPeter Avalos /* 163*36e94dc5SPeter Avalos * If we are a child, the free our parent to decrement its reference 164*36e94dc5SPeter Avalos * count and possibly free it. 165*36e94dc5SPeter Avalos */ 166*36e94dc5SPeter Avalos if (buf->parent != NULL) { 167*36e94dc5SPeter Avalos sshbuf_free(buf->parent); 168*36e94dc5SPeter Avalos buf->parent = NULL; 169*36e94dc5SPeter Avalos } 170*36e94dc5SPeter Avalos /* 171*36e94dc5SPeter Avalos * If we are a parent with still-extant children, then don't free just 172*36e94dc5SPeter Avalos * yet. The last child's call to sshbuf_free should decrement our 173*36e94dc5SPeter Avalos * refcount to 0 and trigger the actual free. 174*36e94dc5SPeter Avalos */ 175*36e94dc5SPeter Avalos buf->refcount--; 176*36e94dc5SPeter Avalos if (buf->refcount > 0) 177*36e94dc5SPeter Avalos return; 178*36e94dc5SPeter Avalos dont_free = buf->dont_free; 179*36e94dc5SPeter Avalos if (!buf->readonly) { 180*36e94dc5SPeter Avalos bzero(buf->d, buf->alloc); 181*36e94dc5SPeter Avalos free(buf->d); 182*36e94dc5SPeter Avalos } 183*36e94dc5SPeter Avalos bzero(buf, sizeof(*buf)); 184*36e94dc5SPeter Avalos if (!dont_free) 185*36e94dc5SPeter Avalos free(buf); 186*36e94dc5SPeter Avalos } 187*36e94dc5SPeter Avalos 188*36e94dc5SPeter Avalos void 189*36e94dc5SPeter Avalos sshbuf_reset(struct sshbuf *buf) 190*36e94dc5SPeter Avalos { 191*36e94dc5SPeter Avalos u_char *d; 192*36e94dc5SPeter Avalos 193*36e94dc5SPeter Avalos if (buf->readonly || buf->refcount > 1) { 194*36e94dc5SPeter Avalos /* Nonsensical. Just make buffer appear empty */ 195*36e94dc5SPeter Avalos buf->off = buf->size; 196*36e94dc5SPeter Avalos return; 197*36e94dc5SPeter Avalos } 198*36e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) == 0) 199*36e94dc5SPeter Avalos bzero(buf->d, buf->alloc); 200*36e94dc5SPeter Avalos buf->off = buf->size = 0; 201*36e94dc5SPeter Avalos if (buf->alloc != SSHBUF_SIZE_INIT) { 202*36e94dc5SPeter Avalos if ((d = realloc(buf->d, SSHBUF_SIZE_INIT)) != NULL) { 203*36e94dc5SPeter Avalos buf->cd = buf->d = d; 204*36e94dc5SPeter Avalos buf->alloc = SSHBUF_SIZE_INIT; 205*36e94dc5SPeter Avalos } 206*36e94dc5SPeter Avalos } 207*36e94dc5SPeter Avalos } 208*36e94dc5SPeter Avalos 209*36e94dc5SPeter Avalos size_t 210*36e94dc5SPeter Avalos sshbuf_max_size(const struct sshbuf *buf) 211*36e94dc5SPeter Avalos { 212*36e94dc5SPeter Avalos return buf->max_size; 213*36e94dc5SPeter Avalos } 214*36e94dc5SPeter Avalos 215*36e94dc5SPeter Avalos size_t 216*36e94dc5SPeter Avalos sshbuf_alloc(const struct sshbuf *buf) 217*36e94dc5SPeter Avalos { 218*36e94dc5SPeter Avalos return buf->alloc; 219*36e94dc5SPeter Avalos } 220*36e94dc5SPeter Avalos 221*36e94dc5SPeter Avalos const struct sshbuf * 222*36e94dc5SPeter Avalos sshbuf_parent(const struct sshbuf *buf) 223*36e94dc5SPeter Avalos { 224*36e94dc5SPeter Avalos return buf->parent; 225*36e94dc5SPeter Avalos } 226*36e94dc5SPeter Avalos 227*36e94dc5SPeter Avalos u_int 228*36e94dc5SPeter Avalos sshbuf_refcount(const struct sshbuf *buf) 229*36e94dc5SPeter Avalos { 230*36e94dc5SPeter Avalos return buf->refcount; 231*36e94dc5SPeter Avalos } 232*36e94dc5SPeter Avalos 233*36e94dc5SPeter Avalos int 234*36e94dc5SPeter Avalos sshbuf_set_max_size(struct sshbuf *buf, size_t max_size) 235*36e94dc5SPeter Avalos { 236*36e94dc5SPeter Avalos size_t rlen; 237*36e94dc5SPeter Avalos u_char *dp; 238*36e94dc5SPeter Avalos int r; 239*36e94dc5SPeter Avalos 240*36e94dc5SPeter Avalos SSHBUF_DBG(("set max buf = %p len = %zu", buf, max_size)); 241*36e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(buf)) != 0) 242*36e94dc5SPeter Avalos return r; 243*36e94dc5SPeter Avalos if (max_size == buf->max_size) 244*36e94dc5SPeter Avalos return 0; 245*36e94dc5SPeter Avalos if (buf->readonly || buf->refcount > 1) 246*36e94dc5SPeter Avalos return SSH_ERR_BUFFER_READ_ONLY; 247*36e94dc5SPeter Avalos if (max_size > SSHBUF_SIZE_MAX) 248*36e94dc5SPeter Avalos return SSH_ERR_NO_BUFFER_SPACE; 249*36e94dc5SPeter Avalos /* pack and realloc if necessary */ 250*36e94dc5SPeter Avalos sshbuf_maybe_pack(buf, max_size < buf->size); 251*36e94dc5SPeter Avalos if (max_size < buf->alloc && max_size > buf->size) { 252*36e94dc5SPeter Avalos if (buf->size < SSHBUF_SIZE_INIT) 253*36e94dc5SPeter Avalos rlen = SSHBUF_SIZE_INIT; 254*36e94dc5SPeter Avalos else 255*36e94dc5SPeter Avalos rlen = roundup(buf->size, SSHBUF_SIZE_INC); 256*36e94dc5SPeter Avalos if (rlen > max_size) 257*36e94dc5SPeter Avalos rlen = max_size; 258*36e94dc5SPeter Avalos bzero(buf->d + buf->size, buf->alloc - buf->size); 259*36e94dc5SPeter Avalos SSHBUF_DBG(("new alloc = %zu", rlen)); 260*36e94dc5SPeter Avalos if ((dp = realloc(buf->d, rlen)) == NULL) 261*36e94dc5SPeter Avalos return SSH_ERR_ALLOC_FAIL; 262*36e94dc5SPeter Avalos buf->cd = buf->d = dp; 263*36e94dc5SPeter Avalos buf->alloc = rlen; 264*36e94dc5SPeter Avalos } 265*36e94dc5SPeter Avalos SSHBUF_TELL("new-max"); 266*36e94dc5SPeter Avalos if (max_size < buf->alloc) 267*36e94dc5SPeter Avalos return SSH_ERR_NO_BUFFER_SPACE; 268*36e94dc5SPeter Avalos buf->max_size = max_size; 269*36e94dc5SPeter Avalos return 0; 270*36e94dc5SPeter Avalos } 271*36e94dc5SPeter Avalos 272*36e94dc5SPeter Avalos size_t 273*36e94dc5SPeter Avalos sshbuf_len(const struct sshbuf *buf) 274*36e94dc5SPeter Avalos { 275*36e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0) 276*36e94dc5SPeter Avalos return 0; 277*36e94dc5SPeter Avalos return buf->size - buf->off; 278*36e94dc5SPeter Avalos } 279*36e94dc5SPeter Avalos 280*36e94dc5SPeter Avalos size_t 281*36e94dc5SPeter Avalos sshbuf_avail(const struct sshbuf *buf) 282*36e94dc5SPeter Avalos { 283*36e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) 284*36e94dc5SPeter Avalos return 0; 285*36e94dc5SPeter Avalos return buf->max_size - (buf->size - buf->off); 286*36e94dc5SPeter Avalos } 287*36e94dc5SPeter Avalos 288*36e94dc5SPeter Avalos const u_char * 289*36e94dc5SPeter Avalos sshbuf_ptr(const struct sshbuf *buf) 290*36e94dc5SPeter Avalos { 291*36e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0) 292*36e94dc5SPeter Avalos return NULL; 293*36e94dc5SPeter Avalos return buf->cd + buf->off; 294*36e94dc5SPeter Avalos } 295*36e94dc5SPeter Avalos 296*36e94dc5SPeter Avalos u_char * 297*36e94dc5SPeter Avalos sshbuf_mutable_ptr(const struct sshbuf *buf) 298*36e94dc5SPeter Avalos { 299*36e94dc5SPeter Avalos if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) 300*36e94dc5SPeter Avalos return NULL; 301*36e94dc5SPeter Avalos return buf->d + buf->off; 302*36e94dc5SPeter Avalos } 303*36e94dc5SPeter Avalos 304*36e94dc5SPeter Avalos int 305*36e94dc5SPeter Avalos sshbuf_check_reserve(const struct sshbuf *buf, size_t len) 306*36e94dc5SPeter Avalos { 307*36e94dc5SPeter Avalos int r; 308*36e94dc5SPeter Avalos 309*36e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(buf)) != 0) 310*36e94dc5SPeter Avalos return r; 311*36e94dc5SPeter Avalos if (buf->readonly || buf->refcount > 1) 312*36e94dc5SPeter Avalos return SSH_ERR_BUFFER_READ_ONLY; 313*36e94dc5SPeter Avalos SSHBUF_TELL("check"); 314*36e94dc5SPeter Avalos /* Check that len is reasonable and that max_size + available < len */ 315*36e94dc5SPeter Avalos if (len > buf->max_size || buf->max_size - len < buf->size - buf->off) 316*36e94dc5SPeter Avalos return SSH_ERR_NO_BUFFER_SPACE; 317*36e94dc5SPeter Avalos return 0; 318*36e94dc5SPeter Avalos } 319*36e94dc5SPeter Avalos 320*36e94dc5SPeter Avalos int 321*36e94dc5SPeter Avalos sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp) 322*36e94dc5SPeter Avalos { 323*36e94dc5SPeter Avalos size_t rlen, need; 324*36e94dc5SPeter Avalos u_char *dp; 325*36e94dc5SPeter Avalos int r; 326*36e94dc5SPeter Avalos 327*36e94dc5SPeter Avalos if (dpp != NULL) 328*36e94dc5SPeter Avalos *dpp = NULL; 329*36e94dc5SPeter Avalos 330*36e94dc5SPeter Avalos SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len)); 331*36e94dc5SPeter Avalos if ((r = sshbuf_check_reserve(buf, len)) != 0) 332*36e94dc5SPeter Avalos return r; 333*36e94dc5SPeter Avalos /* 334*36e94dc5SPeter Avalos * If the requested allocation appended would push us past max_size 335*36e94dc5SPeter Avalos * then pack the buffer, zeroing buf->off. 336*36e94dc5SPeter Avalos */ 337*36e94dc5SPeter Avalos sshbuf_maybe_pack(buf, buf->size + len > buf->max_size); 338*36e94dc5SPeter Avalos SSHBUF_TELL("reserve"); 339*36e94dc5SPeter Avalos if (len + buf->size > buf->alloc) { 340*36e94dc5SPeter Avalos /* 341*36e94dc5SPeter Avalos * Prefer to alloc in SSHBUF_SIZE_INC units, but 342*36e94dc5SPeter Avalos * allocate less if doing so would overflow max_size. 343*36e94dc5SPeter Avalos */ 344*36e94dc5SPeter Avalos need = len + buf->size - buf->alloc; 345*36e94dc5SPeter Avalos rlen = roundup(buf->alloc + need, SSHBUF_SIZE_INC); 346*36e94dc5SPeter Avalos SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen)); 347*36e94dc5SPeter Avalos if (rlen > buf->max_size) 348*36e94dc5SPeter Avalos rlen = buf->alloc + need; 349*36e94dc5SPeter Avalos SSHBUF_DBG(("adjusted rlen %zu", rlen)); 350*36e94dc5SPeter Avalos if ((dp = realloc(buf->d, rlen)) == NULL) { 351*36e94dc5SPeter Avalos SSHBUF_DBG(("realloc fail")); 352*36e94dc5SPeter Avalos if (dpp != NULL) 353*36e94dc5SPeter Avalos *dpp = NULL; 354*36e94dc5SPeter Avalos return SSH_ERR_ALLOC_FAIL; 355*36e94dc5SPeter Avalos } 356*36e94dc5SPeter Avalos buf->alloc = rlen; 357*36e94dc5SPeter Avalos buf->cd = buf->d = dp; 358*36e94dc5SPeter Avalos if ((r = sshbuf_check_reserve(buf, len)) < 0) { 359*36e94dc5SPeter Avalos /* shouldn't fail */ 360*36e94dc5SPeter Avalos if (dpp != NULL) 361*36e94dc5SPeter Avalos *dpp = NULL; 362*36e94dc5SPeter Avalos return r; 363*36e94dc5SPeter Avalos } 364*36e94dc5SPeter Avalos } 365*36e94dc5SPeter Avalos dp = buf->d + buf->size; 366*36e94dc5SPeter Avalos buf->size += len; 367*36e94dc5SPeter Avalos SSHBUF_TELL("done"); 368*36e94dc5SPeter Avalos if (dpp != NULL) 369*36e94dc5SPeter Avalos *dpp = dp; 370*36e94dc5SPeter Avalos return 0; 371*36e94dc5SPeter Avalos } 372*36e94dc5SPeter Avalos 373*36e94dc5SPeter Avalos int 374*36e94dc5SPeter Avalos sshbuf_consume(struct sshbuf *buf, size_t len) 375*36e94dc5SPeter Avalos { 376*36e94dc5SPeter Avalos int r; 377*36e94dc5SPeter Avalos 378*36e94dc5SPeter Avalos SSHBUF_DBG(("len = %zu", len)); 379*36e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(buf)) != 0) 380*36e94dc5SPeter Avalos return r; 381*36e94dc5SPeter Avalos if (len == 0) 382*36e94dc5SPeter Avalos return 0; 383*36e94dc5SPeter Avalos if (len > sshbuf_len(buf)) 384*36e94dc5SPeter Avalos return SSH_ERR_MESSAGE_INCOMPLETE; 385*36e94dc5SPeter Avalos buf->off += len; 386*36e94dc5SPeter Avalos SSHBUF_TELL("done"); 387*36e94dc5SPeter Avalos return 0; 388*36e94dc5SPeter Avalos } 389*36e94dc5SPeter Avalos 390*36e94dc5SPeter Avalos int 391*36e94dc5SPeter Avalos sshbuf_consume_end(struct sshbuf *buf, size_t len) 392*36e94dc5SPeter Avalos { 393*36e94dc5SPeter Avalos int r; 394*36e94dc5SPeter Avalos 395*36e94dc5SPeter Avalos SSHBUF_DBG(("len = %zu", len)); 396*36e94dc5SPeter Avalos if ((r = sshbuf_check_sanity(buf)) != 0) 397*36e94dc5SPeter Avalos return r; 398*36e94dc5SPeter Avalos if (len == 0) 399*36e94dc5SPeter Avalos return 0; 400*36e94dc5SPeter Avalos if (len > sshbuf_len(buf)) 401*36e94dc5SPeter Avalos return SSH_ERR_MESSAGE_INCOMPLETE; 402*36e94dc5SPeter Avalos buf->size -= len; 403*36e94dc5SPeter Avalos SSHBUF_TELL("done"); 404*36e94dc5SPeter Avalos return 0; 405*36e94dc5SPeter Avalos } 406*36e94dc5SPeter Avalos 407