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