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