xref: /freebsd-src/crypto/openssh/sshbuf-getput-basic.c (revision a0ee8cc636cd5c2374ec44ca71226564ea0bca95)
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