1*a0ee8cc6SDag-Erling Smørgrav /* $OpenBSD: sshbuf-getput-basic.c,v 1.1 2014/04/30 05:29:56 djm Exp $ */ 2*a0ee8cc6SDag-Erling Smørgrav /* 3*a0ee8cc6SDag-Erling Smørgrav * Copyright (c) 2011 Damien Miller 4*a0ee8cc6SDag-Erling Smørgrav * 5*a0ee8cc6SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 6*a0ee8cc6SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 7*a0ee8cc6SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 8*a0ee8cc6SDag-Erling Smørgrav * 9*a0ee8cc6SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*a0ee8cc6SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*a0ee8cc6SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*a0ee8cc6SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*a0ee8cc6SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*a0ee8cc6SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*a0ee8cc6SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*a0ee8cc6SDag-Erling Smørgrav */ 17*a0ee8cc6SDag-Erling Smørgrav 18*a0ee8cc6SDag-Erling Smørgrav #define SSHBUF_INTERNAL 19*a0ee8cc6SDag-Erling Smørgrav #include "includes.h" 20*a0ee8cc6SDag-Erling Smørgrav 21*a0ee8cc6SDag-Erling Smørgrav #include <sys/types.h> 22*a0ee8cc6SDag-Erling Smørgrav #include <stdlib.h> 23*a0ee8cc6SDag-Erling Smørgrav #include <stdio.h> 24*a0ee8cc6SDag-Erling Smørgrav #include <string.h> 25*a0ee8cc6SDag-Erling Smørgrav 26*a0ee8cc6SDag-Erling Smørgrav #include "ssherr.h" 27*a0ee8cc6SDag-Erling Smørgrav #include "sshbuf.h" 28*a0ee8cc6SDag-Erling Smørgrav 29*a0ee8cc6SDag-Erling Smørgrav int 30*a0ee8cc6SDag-Erling Smørgrav sshbuf_get(struct sshbuf *buf, void *v, size_t len) 31*a0ee8cc6SDag-Erling Smørgrav { 32*a0ee8cc6SDag-Erling Smørgrav const u_char *p = sshbuf_ptr(buf); 33*a0ee8cc6SDag-Erling Smørgrav int r; 34*a0ee8cc6SDag-Erling Smørgrav 35*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_consume(buf, len)) < 0) 36*a0ee8cc6SDag-Erling Smørgrav return r; 37*a0ee8cc6SDag-Erling Smørgrav if (v != NULL) 38*a0ee8cc6SDag-Erling Smørgrav memcpy(v, p, len); 39*a0ee8cc6SDag-Erling Smørgrav return 0; 40*a0ee8cc6SDag-Erling Smørgrav } 41*a0ee8cc6SDag-Erling Smørgrav 42*a0ee8cc6SDag-Erling Smørgrav int 43*a0ee8cc6SDag-Erling Smørgrav sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp) 44*a0ee8cc6SDag-Erling Smørgrav { 45*a0ee8cc6SDag-Erling Smørgrav const u_char *p = sshbuf_ptr(buf); 46*a0ee8cc6SDag-Erling Smørgrav int r; 47*a0ee8cc6SDag-Erling Smørgrav 48*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_consume(buf, 8)) < 0) 49*a0ee8cc6SDag-Erling Smørgrav return r; 50*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) 51*a0ee8cc6SDag-Erling Smørgrav *valp = PEEK_U64(p); 52*a0ee8cc6SDag-Erling Smørgrav return 0; 53*a0ee8cc6SDag-Erling Smørgrav } 54*a0ee8cc6SDag-Erling Smørgrav 55*a0ee8cc6SDag-Erling Smørgrav int 56*a0ee8cc6SDag-Erling Smørgrav sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp) 57*a0ee8cc6SDag-Erling Smørgrav { 58*a0ee8cc6SDag-Erling Smørgrav const u_char *p = sshbuf_ptr(buf); 59*a0ee8cc6SDag-Erling Smørgrav int r; 60*a0ee8cc6SDag-Erling Smørgrav 61*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_consume(buf, 4)) < 0) 62*a0ee8cc6SDag-Erling Smørgrav return r; 63*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) 64*a0ee8cc6SDag-Erling Smørgrav *valp = PEEK_U32(p); 65*a0ee8cc6SDag-Erling Smørgrav return 0; 66*a0ee8cc6SDag-Erling Smørgrav } 67*a0ee8cc6SDag-Erling Smørgrav 68*a0ee8cc6SDag-Erling Smørgrav int 69*a0ee8cc6SDag-Erling Smørgrav sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp) 70*a0ee8cc6SDag-Erling Smørgrav { 71*a0ee8cc6SDag-Erling Smørgrav const u_char *p = sshbuf_ptr(buf); 72*a0ee8cc6SDag-Erling Smørgrav int r; 73*a0ee8cc6SDag-Erling Smørgrav 74*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_consume(buf, 2)) < 0) 75*a0ee8cc6SDag-Erling Smørgrav return r; 76*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) 77*a0ee8cc6SDag-Erling Smørgrav *valp = PEEK_U16(p); 78*a0ee8cc6SDag-Erling Smørgrav return 0; 79*a0ee8cc6SDag-Erling Smørgrav } 80*a0ee8cc6SDag-Erling Smørgrav 81*a0ee8cc6SDag-Erling Smørgrav int 82*a0ee8cc6SDag-Erling Smørgrav sshbuf_get_u8(struct sshbuf *buf, u_char *valp) 83*a0ee8cc6SDag-Erling Smørgrav { 84*a0ee8cc6SDag-Erling Smørgrav const u_char *p = sshbuf_ptr(buf); 85*a0ee8cc6SDag-Erling Smørgrav int r; 86*a0ee8cc6SDag-Erling Smørgrav 87*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_consume(buf, 1)) < 0) 88*a0ee8cc6SDag-Erling Smørgrav return r; 89*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) 90*a0ee8cc6SDag-Erling Smørgrav *valp = (u_int8_t)*p; 91*a0ee8cc6SDag-Erling Smørgrav return 0; 92*a0ee8cc6SDag-Erling Smørgrav } 93*a0ee8cc6SDag-Erling Smørgrav 94*a0ee8cc6SDag-Erling Smørgrav int 95*a0ee8cc6SDag-Erling Smørgrav sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp) 96*a0ee8cc6SDag-Erling Smørgrav { 97*a0ee8cc6SDag-Erling Smørgrav const u_char *val; 98*a0ee8cc6SDag-Erling Smørgrav size_t len; 99*a0ee8cc6SDag-Erling Smørgrav int r; 100*a0ee8cc6SDag-Erling Smørgrav 101*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) 102*a0ee8cc6SDag-Erling Smørgrav *valp = NULL; 103*a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL) 104*a0ee8cc6SDag-Erling Smørgrav *lenp = 0; 105*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_get_string_direct(buf, &val, &len)) < 0) 106*a0ee8cc6SDag-Erling Smørgrav return r; 107*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) { 108*a0ee8cc6SDag-Erling Smørgrav if ((*valp = malloc(len + 1)) == NULL) { 109*a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); 110*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL; 111*a0ee8cc6SDag-Erling Smørgrav } 112*a0ee8cc6SDag-Erling Smørgrav memcpy(*valp, val, len); 113*a0ee8cc6SDag-Erling Smørgrav (*valp)[len] = '\0'; 114*a0ee8cc6SDag-Erling Smørgrav } 115*a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL) 116*a0ee8cc6SDag-Erling Smørgrav *lenp = len; 117*a0ee8cc6SDag-Erling Smørgrav return 0; 118*a0ee8cc6SDag-Erling Smørgrav } 119*a0ee8cc6SDag-Erling Smørgrav 120*a0ee8cc6SDag-Erling Smørgrav int 121*a0ee8cc6SDag-Erling Smørgrav sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp) 122*a0ee8cc6SDag-Erling Smørgrav { 123*a0ee8cc6SDag-Erling Smørgrav size_t len; 124*a0ee8cc6SDag-Erling Smørgrav const u_char *p; 125*a0ee8cc6SDag-Erling Smørgrav int r; 126*a0ee8cc6SDag-Erling Smørgrav 127*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) 128*a0ee8cc6SDag-Erling Smørgrav *valp = NULL; 129*a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL) 130*a0ee8cc6SDag-Erling Smørgrav *lenp = 0; 131*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_peek_string_direct(buf, &p, &len)) < 0) 132*a0ee8cc6SDag-Erling Smørgrav return r; 133*a0ee8cc6SDag-Erling Smørgrav if (valp != 0) 134*a0ee8cc6SDag-Erling Smørgrav *valp = p; 135*a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL) 136*a0ee8cc6SDag-Erling Smørgrav *lenp = len; 137*a0ee8cc6SDag-Erling Smørgrav if (sshbuf_consume(buf, len + 4) != 0) { 138*a0ee8cc6SDag-Erling Smørgrav /* Shouldn't happen */ 139*a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); 140*a0ee8cc6SDag-Erling Smørgrav SSHBUF_ABORT(); 141*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INTERNAL_ERROR; 142*a0ee8cc6SDag-Erling Smørgrav } 143*a0ee8cc6SDag-Erling Smørgrav return 0; 144*a0ee8cc6SDag-Erling Smørgrav } 145*a0ee8cc6SDag-Erling Smørgrav 146*a0ee8cc6SDag-Erling Smørgrav int 147*a0ee8cc6SDag-Erling Smørgrav sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, 148*a0ee8cc6SDag-Erling Smørgrav size_t *lenp) 149*a0ee8cc6SDag-Erling Smørgrav { 150*a0ee8cc6SDag-Erling Smørgrav u_int32_t len; 151*a0ee8cc6SDag-Erling Smørgrav const u_char *p = sshbuf_ptr(buf); 152*a0ee8cc6SDag-Erling Smørgrav 153*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) 154*a0ee8cc6SDag-Erling Smørgrav *valp = NULL; 155*a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL) 156*a0ee8cc6SDag-Erling Smørgrav *lenp = 0; 157*a0ee8cc6SDag-Erling Smørgrav if (sshbuf_len(buf) < 4) { 158*a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE")); 159*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_MESSAGE_INCOMPLETE; 160*a0ee8cc6SDag-Erling Smørgrav } 161*a0ee8cc6SDag-Erling Smørgrav len = PEEK_U32(p); 162*a0ee8cc6SDag-Erling Smørgrav if (len > SSHBUF_SIZE_MAX - 4) { 163*a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_STRING_TOO_LARGE")); 164*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_STRING_TOO_LARGE; 165*a0ee8cc6SDag-Erling Smørgrav } 166*a0ee8cc6SDag-Erling Smørgrav if (sshbuf_len(buf) - 4 < len) { 167*a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE")); 168*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_MESSAGE_INCOMPLETE; 169*a0ee8cc6SDag-Erling Smørgrav } 170*a0ee8cc6SDag-Erling Smørgrav if (valp != 0) 171*a0ee8cc6SDag-Erling Smørgrav *valp = p + 4; 172*a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL) 173*a0ee8cc6SDag-Erling Smørgrav *lenp = len; 174*a0ee8cc6SDag-Erling Smørgrav return 0; 175*a0ee8cc6SDag-Erling Smørgrav } 176*a0ee8cc6SDag-Erling Smørgrav 177*a0ee8cc6SDag-Erling Smørgrav int 178*a0ee8cc6SDag-Erling Smørgrav sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp) 179*a0ee8cc6SDag-Erling Smørgrav { 180*a0ee8cc6SDag-Erling Smørgrav size_t len; 181*a0ee8cc6SDag-Erling Smørgrav const u_char *p, *z; 182*a0ee8cc6SDag-Erling Smørgrav int r; 183*a0ee8cc6SDag-Erling Smørgrav 184*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) 185*a0ee8cc6SDag-Erling Smørgrav *valp = NULL; 186*a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL) 187*a0ee8cc6SDag-Erling Smørgrav *lenp = 0; 188*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0) 189*a0ee8cc6SDag-Erling Smørgrav return r; 190*a0ee8cc6SDag-Erling Smørgrav /* Allow a \0 only at the end of the string */ 191*a0ee8cc6SDag-Erling Smørgrav if (len > 0 && 192*a0ee8cc6SDag-Erling Smørgrav (z = memchr(p , '\0', len)) != NULL && z < p + len - 1) { 193*a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_INVALID_FORMAT")); 194*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_FORMAT; 195*a0ee8cc6SDag-Erling Smørgrav } 196*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_skip_string(buf)) != 0) 197*a0ee8cc6SDag-Erling Smørgrav return -1; 198*a0ee8cc6SDag-Erling Smørgrav if (valp != NULL) { 199*a0ee8cc6SDag-Erling Smørgrav if ((*valp = malloc(len + 1)) == NULL) { 200*a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); 201*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL; 202*a0ee8cc6SDag-Erling Smørgrav } 203*a0ee8cc6SDag-Erling Smørgrav memcpy(*valp, p, len); 204*a0ee8cc6SDag-Erling Smørgrav (*valp)[len] = '\0'; 205*a0ee8cc6SDag-Erling Smørgrav } 206*a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL) 207*a0ee8cc6SDag-Erling Smørgrav *lenp = (size_t)len; 208*a0ee8cc6SDag-Erling Smørgrav return 0; 209*a0ee8cc6SDag-Erling Smørgrav } 210*a0ee8cc6SDag-Erling Smørgrav 211*a0ee8cc6SDag-Erling Smørgrav int 212*a0ee8cc6SDag-Erling Smørgrav sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v) 213*a0ee8cc6SDag-Erling Smørgrav { 214*a0ee8cc6SDag-Erling Smørgrav u_int32_t len; 215*a0ee8cc6SDag-Erling Smørgrav u_char *p; 216*a0ee8cc6SDag-Erling Smørgrav int r; 217*a0ee8cc6SDag-Erling Smørgrav 218*a0ee8cc6SDag-Erling Smørgrav /* 219*a0ee8cc6SDag-Erling Smørgrav * Use sshbuf_peek_string_direct() to figure out if there is 220*a0ee8cc6SDag-Erling Smørgrav * a complete string in 'buf' and copy the string directly 221*a0ee8cc6SDag-Erling Smørgrav * into 'v'. 222*a0ee8cc6SDag-Erling Smørgrav */ 223*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_peek_string_direct(buf, NULL, NULL)) != 0 || 224*a0ee8cc6SDag-Erling Smørgrav (r = sshbuf_get_u32(buf, &len)) != 0 || 225*a0ee8cc6SDag-Erling Smørgrav (r = sshbuf_reserve(v, len, &p)) != 0 || 226*a0ee8cc6SDag-Erling Smørgrav (r = sshbuf_get(buf, p, len)) != 0) 227*a0ee8cc6SDag-Erling Smørgrav return r; 228*a0ee8cc6SDag-Erling Smørgrav return 0; 229*a0ee8cc6SDag-Erling Smørgrav } 230*a0ee8cc6SDag-Erling Smørgrav 231*a0ee8cc6SDag-Erling Smørgrav int 232*a0ee8cc6SDag-Erling Smørgrav sshbuf_put(struct sshbuf *buf, const void *v, size_t len) 233*a0ee8cc6SDag-Erling Smørgrav { 234*a0ee8cc6SDag-Erling Smørgrav u_char *p; 235*a0ee8cc6SDag-Erling Smørgrav int r; 236*a0ee8cc6SDag-Erling Smørgrav 237*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_reserve(buf, len, &p)) < 0) 238*a0ee8cc6SDag-Erling Smørgrav return r; 239*a0ee8cc6SDag-Erling Smørgrav memcpy(p, v, len); 240*a0ee8cc6SDag-Erling Smørgrav return 0; 241*a0ee8cc6SDag-Erling Smørgrav } 242*a0ee8cc6SDag-Erling Smørgrav 243*a0ee8cc6SDag-Erling Smørgrav int 244*a0ee8cc6SDag-Erling Smørgrav sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v) 245*a0ee8cc6SDag-Erling Smørgrav { 246*a0ee8cc6SDag-Erling Smørgrav return sshbuf_put(buf, sshbuf_ptr(v), sshbuf_len(v)); 247*a0ee8cc6SDag-Erling Smørgrav } 248*a0ee8cc6SDag-Erling Smørgrav 249*a0ee8cc6SDag-Erling Smørgrav int 250*a0ee8cc6SDag-Erling Smørgrav sshbuf_putf(struct sshbuf *buf, const char *fmt, ...) 251*a0ee8cc6SDag-Erling Smørgrav { 252*a0ee8cc6SDag-Erling Smørgrav va_list ap; 253*a0ee8cc6SDag-Erling Smørgrav int r; 254*a0ee8cc6SDag-Erling Smørgrav 255*a0ee8cc6SDag-Erling Smørgrav va_start(ap, fmt); 256*a0ee8cc6SDag-Erling Smørgrav r = sshbuf_putfv(buf, fmt, ap); 257*a0ee8cc6SDag-Erling Smørgrav va_end(ap); 258*a0ee8cc6SDag-Erling Smørgrav return r; 259*a0ee8cc6SDag-Erling Smørgrav } 260*a0ee8cc6SDag-Erling Smørgrav 261*a0ee8cc6SDag-Erling Smørgrav int 262*a0ee8cc6SDag-Erling Smørgrav sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap) 263*a0ee8cc6SDag-Erling Smørgrav { 264*a0ee8cc6SDag-Erling Smørgrav va_list ap2; 265*a0ee8cc6SDag-Erling Smørgrav int r, len; 266*a0ee8cc6SDag-Erling Smørgrav u_char *p; 267*a0ee8cc6SDag-Erling Smørgrav 268*a0ee8cc6SDag-Erling Smørgrav va_copy(ap2, ap); 269*a0ee8cc6SDag-Erling Smørgrav if ((len = vsnprintf(NULL, 0, fmt, ap2)) < 0) { 270*a0ee8cc6SDag-Erling Smørgrav r = SSH_ERR_INVALID_ARGUMENT; 271*a0ee8cc6SDag-Erling Smørgrav goto out; 272*a0ee8cc6SDag-Erling Smørgrav } 273*a0ee8cc6SDag-Erling Smørgrav if (len == 0) { 274*a0ee8cc6SDag-Erling Smørgrav r = 0; 275*a0ee8cc6SDag-Erling Smørgrav goto out; /* Nothing to do */ 276*a0ee8cc6SDag-Erling Smørgrav } 277*a0ee8cc6SDag-Erling Smørgrav va_end(ap2); 278*a0ee8cc6SDag-Erling Smørgrav va_copy(ap2, ap); 279*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_reserve(buf, (size_t)len + 1, &p)) < 0) 280*a0ee8cc6SDag-Erling Smørgrav goto out; 281*a0ee8cc6SDag-Erling Smørgrav if ((r = vsnprintf((char *)p, len + 1, fmt, ap2)) != len) { 282*a0ee8cc6SDag-Erling Smørgrav r = SSH_ERR_INTERNAL_ERROR; 283*a0ee8cc6SDag-Erling Smørgrav goto out; /* Shouldn't happen */ 284*a0ee8cc6SDag-Erling Smørgrav } 285*a0ee8cc6SDag-Erling Smørgrav /* Consume terminating \0 */ 286*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_consume_end(buf, 1)) != 0) 287*a0ee8cc6SDag-Erling Smørgrav goto out; 288*a0ee8cc6SDag-Erling Smørgrav r = 0; 289*a0ee8cc6SDag-Erling Smørgrav out: 290*a0ee8cc6SDag-Erling Smørgrav va_end(ap2); 291*a0ee8cc6SDag-Erling Smørgrav return r; 292*a0ee8cc6SDag-Erling Smørgrav } 293*a0ee8cc6SDag-Erling Smørgrav 294*a0ee8cc6SDag-Erling Smørgrav int 295*a0ee8cc6SDag-Erling Smørgrav sshbuf_put_u64(struct sshbuf *buf, u_int64_t val) 296*a0ee8cc6SDag-Erling Smørgrav { 297*a0ee8cc6SDag-Erling Smørgrav u_char *p; 298*a0ee8cc6SDag-Erling Smørgrav int r; 299*a0ee8cc6SDag-Erling Smørgrav 300*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_reserve(buf, 8, &p)) < 0) 301*a0ee8cc6SDag-Erling Smørgrav return r; 302*a0ee8cc6SDag-Erling Smørgrav POKE_U64(p, val); 303*a0ee8cc6SDag-Erling Smørgrav return 0; 304*a0ee8cc6SDag-Erling Smørgrav } 305*a0ee8cc6SDag-Erling Smørgrav 306*a0ee8cc6SDag-Erling Smørgrav int 307*a0ee8cc6SDag-Erling Smørgrav sshbuf_put_u32(struct sshbuf *buf, u_int32_t val) 308*a0ee8cc6SDag-Erling Smørgrav { 309*a0ee8cc6SDag-Erling Smørgrav u_char *p; 310*a0ee8cc6SDag-Erling Smørgrav int r; 311*a0ee8cc6SDag-Erling Smørgrav 312*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_reserve(buf, 4, &p)) < 0) 313*a0ee8cc6SDag-Erling Smørgrav return r; 314*a0ee8cc6SDag-Erling Smørgrav POKE_U32(p, val); 315*a0ee8cc6SDag-Erling Smørgrav return 0; 316*a0ee8cc6SDag-Erling Smørgrav } 317*a0ee8cc6SDag-Erling Smørgrav 318*a0ee8cc6SDag-Erling Smørgrav int 319*a0ee8cc6SDag-Erling Smørgrav sshbuf_put_u16(struct sshbuf *buf, u_int16_t val) 320*a0ee8cc6SDag-Erling Smørgrav { 321*a0ee8cc6SDag-Erling Smørgrav u_char *p; 322*a0ee8cc6SDag-Erling Smørgrav int r; 323*a0ee8cc6SDag-Erling Smørgrav 324*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_reserve(buf, 2, &p)) < 0) 325*a0ee8cc6SDag-Erling Smørgrav return r; 326*a0ee8cc6SDag-Erling Smørgrav POKE_U16(p, val); 327*a0ee8cc6SDag-Erling Smørgrav return 0; 328*a0ee8cc6SDag-Erling Smørgrav } 329*a0ee8cc6SDag-Erling Smørgrav 330*a0ee8cc6SDag-Erling Smørgrav int 331*a0ee8cc6SDag-Erling Smørgrav sshbuf_put_u8(struct sshbuf *buf, u_char val) 332*a0ee8cc6SDag-Erling Smørgrav { 333*a0ee8cc6SDag-Erling Smørgrav u_char *p; 334*a0ee8cc6SDag-Erling Smørgrav int r; 335*a0ee8cc6SDag-Erling Smørgrav 336*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_reserve(buf, 1, &p)) < 0) 337*a0ee8cc6SDag-Erling Smørgrav return r; 338*a0ee8cc6SDag-Erling Smørgrav p[0] = val; 339*a0ee8cc6SDag-Erling Smørgrav return 0; 340*a0ee8cc6SDag-Erling Smørgrav } 341*a0ee8cc6SDag-Erling Smørgrav 342*a0ee8cc6SDag-Erling Smørgrav int 343*a0ee8cc6SDag-Erling Smørgrav sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len) 344*a0ee8cc6SDag-Erling Smørgrav { 345*a0ee8cc6SDag-Erling Smørgrav u_char *d; 346*a0ee8cc6SDag-Erling Smørgrav int r; 347*a0ee8cc6SDag-Erling Smørgrav 348*a0ee8cc6SDag-Erling Smørgrav if (len > SSHBUF_SIZE_MAX - 4) { 349*a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE")); 350*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_NO_BUFFER_SPACE; 351*a0ee8cc6SDag-Erling Smørgrav } 352*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_reserve(buf, len + 4, &d)) < 0) 353*a0ee8cc6SDag-Erling Smørgrav return r; 354*a0ee8cc6SDag-Erling Smørgrav POKE_U32(d, len); 355*a0ee8cc6SDag-Erling Smørgrav memcpy(d + 4, v, len); 356*a0ee8cc6SDag-Erling Smørgrav return 0; 357*a0ee8cc6SDag-Erling Smørgrav } 358*a0ee8cc6SDag-Erling Smørgrav 359*a0ee8cc6SDag-Erling Smørgrav int 360*a0ee8cc6SDag-Erling Smørgrav sshbuf_put_cstring(struct sshbuf *buf, const char *v) 361*a0ee8cc6SDag-Erling Smørgrav { 362*a0ee8cc6SDag-Erling Smørgrav return sshbuf_put_string(buf, (u_char *)v, strlen(v)); 363*a0ee8cc6SDag-Erling Smørgrav } 364*a0ee8cc6SDag-Erling Smørgrav 365*a0ee8cc6SDag-Erling Smørgrav int 366*a0ee8cc6SDag-Erling Smørgrav sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v) 367*a0ee8cc6SDag-Erling Smørgrav { 368*a0ee8cc6SDag-Erling Smørgrav return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v)); 369*a0ee8cc6SDag-Erling Smørgrav } 370*a0ee8cc6SDag-Erling Smørgrav 371*a0ee8cc6SDag-Erling Smørgrav int 372*a0ee8cc6SDag-Erling Smørgrav sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp) 373*a0ee8cc6SDag-Erling Smørgrav { 374*a0ee8cc6SDag-Erling Smørgrav const u_char *p; 375*a0ee8cc6SDag-Erling Smørgrav size_t len; 376*a0ee8cc6SDag-Erling Smørgrav struct sshbuf *ret; 377*a0ee8cc6SDag-Erling Smørgrav int r; 378*a0ee8cc6SDag-Erling Smørgrav 379*a0ee8cc6SDag-Erling Smørgrav if (buf == NULL || bufp == NULL) 380*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT; 381*a0ee8cc6SDag-Erling Smørgrav *bufp = NULL; 382*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0) 383*a0ee8cc6SDag-Erling Smørgrav return r; 384*a0ee8cc6SDag-Erling Smørgrav if ((ret = sshbuf_from(p, len)) == NULL) 385*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL; 386*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_consume(buf, len + 4)) != 0 || /* Shouldn't happen */ 387*a0ee8cc6SDag-Erling Smørgrav (r = sshbuf_set_parent(ret, buf)) != 0) { 388*a0ee8cc6SDag-Erling Smørgrav sshbuf_free(ret); 389*a0ee8cc6SDag-Erling Smørgrav return r; 390*a0ee8cc6SDag-Erling Smørgrav } 391*a0ee8cc6SDag-Erling Smørgrav *bufp = ret; 392*a0ee8cc6SDag-Erling Smørgrav return 0; 393*a0ee8cc6SDag-Erling Smørgrav } 394*a0ee8cc6SDag-Erling Smørgrav 395*a0ee8cc6SDag-Erling Smørgrav int 396*a0ee8cc6SDag-Erling Smørgrav sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len) 397*a0ee8cc6SDag-Erling Smørgrav { 398*a0ee8cc6SDag-Erling Smørgrav u_char *d; 399*a0ee8cc6SDag-Erling Smørgrav const u_char *s = (const u_char *)v; 400*a0ee8cc6SDag-Erling Smørgrav int r, prepend; 401*a0ee8cc6SDag-Erling Smørgrav 402*a0ee8cc6SDag-Erling Smørgrav if (len > SSHBUF_SIZE_MAX - 5) { 403*a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE")); 404*a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_NO_BUFFER_SPACE; 405*a0ee8cc6SDag-Erling Smørgrav } 406*a0ee8cc6SDag-Erling Smørgrav /* Skip leading zero bytes */ 407*a0ee8cc6SDag-Erling Smørgrav for (; len > 0 && *s == 0; len--, s++) 408*a0ee8cc6SDag-Erling Smørgrav ; 409*a0ee8cc6SDag-Erling Smørgrav /* 410*a0ee8cc6SDag-Erling Smørgrav * If most significant bit is set then prepend a zero byte to 411*a0ee8cc6SDag-Erling Smørgrav * avoid interpretation as a negative number. 412*a0ee8cc6SDag-Erling Smørgrav */ 413*a0ee8cc6SDag-Erling Smørgrav prepend = len > 0 && (s[0] & 0x80) != 0; 414*a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_reserve(buf, len + 4 + prepend, &d)) < 0) 415*a0ee8cc6SDag-Erling Smørgrav return r; 416*a0ee8cc6SDag-Erling Smørgrav POKE_U32(d, len + prepend); 417*a0ee8cc6SDag-Erling Smørgrav if (prepend) 418*a0ee8cc6SDag-Erling Smørgrav d[4] = 0; 419*a0ee8cc6SDag-Erling Smørgrav memcpy(d + 4 + prepend, s, len); 420*a0ee8cc6SDag-Erling Smørgrav return 0; 421*a0ee8cc6SDag-Erling Smørgrav } 422