1 | /* $NetBSD: sshbuf.h,v 1.11 2019/04/20 17:16:40 christos Exp $ */ |
2 | /* $OpenBSD: sshbuf.h,v 1.13 2019/01/21 09:54:11 djm Exp $ */ |
3 | /* |
4 | * Copyright (c) 2011 Damien Miller |
5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above |
8 | * copyright notice and this permission notice appear in all copies. |
9 | * |
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ |
18 | |
19 | #ifndef _SSHBUF_H |
20 | #define _SSHBUF_H |
21 | |
22 | #include <sys/types.h> |
23 | #include <stdarg.h> |
24 | #include <stdio.h> |
25 | #include <openssl/bn.h> |
26 | #include <openssl/ec.h> |
27 | |
28 | /* move the following to a more appropriate place and name */ |
29 | #define BUFFER_MAX_LEN_HPN 0x4000000 /* 64MB */ |
30 | |
31 | #define SSHBUF_SIZE_MAX 0x8000000 /* Hard maximum size */ |
32 | #define SSHBUF_REFS_MAX 0x100000 /* Max child buffers */ |
33 | #define SSHBUF_MAX_BIGNUM (16384 / 8) /* Max bignum *bytes* */ |
34 | #define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */ |
35 | |
36 | /* |
37 | * NB. do not depend on the internals of this. It will be made opaque |
38 | * one day. |
39 | */ |
40 | struct sshbuf { |
41 | u_char *d; /* Data */ |
42 | const u_char *cd; /* Const data */ |
43 | size_t off; /* First available byte is buf->d + buf->off */ |
44 | size_t size; /* Last byte is buf->d + buf->size - 1 */ |
45 | size_t max_size; /* Maximum size of buffer */ |
46 | size_t alloc; /* Total bytes allocated to buf->d */ |
47 | int readonly; /* Refers to external, const data */ |
48 | int dont_free; /* Kludge to support sshbuf_init */ |
49 | u_int refcount; /* Tracks self and number of child buffers */ |
50 | struct sshbuf *parent; /* If child, pointer to parent */ |
51 | }; |
52 | |
53 | /* |
54 | * Create a new sshbuf buffer. |
55 | * Returns pointer to buffer on success, or NULL on allocation failure. |
56 | */ |
57 | struct sshbuf *sshbuf_new(void); |
58 | |
59 | /* |
60 | * Create a new, read-only sshbuf buffer from existing data. |
61 | * Returns pointer to buffer on success, or NULL on allocation failure. |
62 | */ |
63 | struct sshbuf *sshbuf_from(const void *blob, size_t len); |
64 | |
65 | /* |
66 | * Create a new, read-only sshbuf buffer from the contents of an existing |
67 | * buffer. The contents of "buf" must not change in the lifetime of the |
68 | * resultant buffer. |
69 | * Returns pointer to buffer on success, or NULL on allocation failure. |
70 | */ |
71 | struct sshbuf *sshbuf_fromb(struct sshbuf *buf); |
72 | |
73 | /* |
74 | * Create a new, read-only sshbuf buffer from the contents of a string in |
75 | * an existing buffer (the string is consumed in the process). |
76 | * The contents of "buf" must not change in the lifetime of the resultant |
77 | * buffer. |
78 | * Returns pointer to buffer on success, or NULL on allocation failure. |
79 | */ |
80 | int sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp); |
81 | |
82 | /* |
83 | * Clear and free buf |
84 | */ |
85 | void sshbuf_free(struct sshbuf *buf); |
86 | |
87 | /* |
88 | * Reset buf, clearing its contents. NB. max_size is preserved. |
89 | */ |
90 | void sshbuf_reset(struct sshbuf *buf); |
91 | |
92 | /* |
93 | * Return the maximum size of buf |
94 | */ |
95 | size_t sshbuf_max_size(const struct sshbuf *buf); |
96 | |
97 | /* |
98 | * Set the maximum size of buf |
99 | * Returns 0 on success, or a negative SSH_ERR_* error code on failure. |
100 | */ |
101 | int sshbuf_set_max_size(struct sshbuf *buf, size_t max_size); |
102 | |
103 | /* |
104 | * Returns the length of data in buf |
105 | */ |
106 | size_t sshbuf_len(const struct sshbuf *buf); |
107 | |
108 | /* |
109 | * Returns number of bytes left in buffer before hitting max_size. |
110 | */ |
111 | size_t sshbuf_avail(const struct sshbuf *buf); |
112 | |
113 | /* |
114 | * Returns a read-only pointer to the start of the data in buf |
115 | */ |
116 | const u_char *sshbuf_ptr(const struct sshbuf *buf); |
117 | |
118 | /* |
119 | * Returns a mutable pointer to the start of the data in buf, or |
120 | * NULL if the buffer is read-only. |
121 | */ |
122 | u_char *sshbuf_mutable_ptr(const struct sshbuf *buf); |
123 | |
124 | /* |
125 | * Check whether a reservation of size len will succeed in buf |
126 | * Safer to use than direct comparisons again sshbuf_avail as it copes |
127 | * with unsigned overflows correctly. |
128 | * Returns 0 on success, or a negative SSH_ERR_* error code on failure. |
129 | */ |
130 | int sshbuf_check_reserve(const struct sshbuf *buf, size_t len); |
131 | |
132 | /* |
133 | * Preallocates len additional bytes in buf. |
134 | * Useful for cases where the caller knows how many bytes will ultimately be |
135 | * required to avoid realloc in the buffer code. |
136 | * Returns 0 on success, or a negative SSH_ERR_* error code on failure. |
137 | */ |
138 | int sshbuf_allocate(struct sshbuf *buf, size_t len); |
139 | |
140 | /* |
141 | * Reserve len bytes in buf. |
142 | * Returns 0 on success and a pointer to the first reserved byte via the |
143 | * optional dpp parameter or a negative * SSH_ERR_* error code on failure. |
144 | */ |
145 | int sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp); |
146 | |
147 | /* |
148 | * Consume len bytes from the start of buf |
149 | * Returns 0 on success, or a negative SSH_ERR_* error code on failure. |
150 | */ |
151 | int sshbuf_consume(struct sshbuf *buf, size_t len); |
152 | |
153 | /* |
154 | * Consume len bytes from the end of buf |
155 | * Returns 0 on success, or a negative SSH_ERR_* error code on failure. |
156 | */ |
157 | int sshbuf_consume_end(struct sshbuf *buf, size_t len); |
158 | |
159 | /* Extract or deposit some bytes */ |
160 | int sshbuf_get(struct sshbuf *buf, void *v, size_t len); |
161 | int sshbuf_put(struct sshbuf *buf, const void *v, size_t len); |
162 | int sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v); |
163 | |
164 | /* Append using a printf(3) format */ |
165 | int sshbuf_putf(struct sshbuf *buf, const char *fmt, ...) |
166 | __attribute__((format(printf, 2, 3))); |
167 | int sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap) |
168 | __printflike(2, 0); |
169 | |
170 | /* Functions to extract or store big-endian words of various sizes */ |
171 | int sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp); |
172 | int sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp); |
173 | int sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp); |
174 | int sshbuf_get_u8(struct sshbuf *buf, u_char *valp); |
175 | int sshbuf_put_u64(struct sshbuf *buf, u_int64_t val); |
176 | int sshbuf_put_u32(struct sshbuf *buf, u_int32_t val); |
177 | int sshbuf_put_u16(struct sshbuf *buf, u_int16_t val); |
178 | int sshbuf_put_u8(struct sshbuf *buf, u_char val); |
179 | |
180 | /* |
181 | * Functions to extract or store SSH wire encoded strings (u32 len || data) |
182 | * The "cstring" variants admit no \0 characters in the string contents. |
183 | * Caller must free *valp. |
184 | */ |
185 | int sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp); |
186 | int sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp); |
187 | int sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v); |
188 | int sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len); |
189 | int sshbuf_put_cstring(struct sshbuf *buf, const char *v); |
190 | int sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v); |
191 | |
192 | /* |
193 | * "Direct" variant of sshbuf_get_string, returns pointer into the sshbuf to |
194 | * avoid an malloc+memcpy. The pointer is guaranteed to be valid until the |
195 | * next sshbuf-modifying function call. Caller does not free. |
196 | */ |
197 | int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, |
198 | size_t *lenp); |
199 | |
200 | /* Skip past a string */ |
201 | #define sshbuf_skip_string(buf) sshbuf_get_string_direct(buf, NULL, NULL) |
202 | |
203 | /* Another variant: "peeks" into the buffer without modifying it */ |
204 | int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, |
205 | size_t *lenp); |
206 | /* XXX peek_u8 / peek_u32 */ |
207 | |
208 | /* |
209 | * Functions to extract or store SSH wire encoded bignums and elliptic |
210 | * curve points. |
211 | */ |
212 | int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp); |
213 | int sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf, |
214 | const u_char **valp, size_t *lenp); |
215 | int sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v); |
216 | int sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len); |
217 | int sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g); |
218 | int sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v); |
219 | int sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g); |
220 | int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v); |
221 | |
222 | /* Dump the contents of the buffer in a human-readable format */ |
223 | void sshbuf_dump(struct sshbuf *buf, FILE *f); |
224 | |
225 | /* Dump specified memory in a human-readable format */ |
226 | void sshbuf_dump_data(const void *s, size_t len, FILE *f); |
227 | |
228 | /* Return the hexadecimal representation of the contents of the buffer */ |
229 | char *sshbuf_dtob16(struct sshbuf *buf); |
230 | |
231 | /* Encode the contents of the buffer as base64 */ |
232 | char *sshbuf_dtob64(struct sshbuf *buf); |
233 | |
234 | /* Decode base64 data and append it to the buffer */ |
235 | int sshbuf_b64tod(struct sshbuf *buf, const char *b64); |
236 | |
237 | /* |
238 | * Duplicate the contents of a buffer to a string (caller to free). |
239 | * Returns NULL on buffer error, or if the buffer contains a premature |
240 | * nul character. |
241 | */ |
242 | char *sshbuf_dup_string(struct sshbuf *buf); |
243 | |
244 | /* Macros for decoding/encoding integers */ |
245 | #define PEEK_U64(p) \ |
246 | (((u_int64_t)(((const u_char *)(p))[0]) << 56) | \ |
247 | ((u_int64_t)(((const u_char *)(p))[1]) << 48) | \ |
248 | ((u_int64_t)(((const u_char *)(p))[2]) << 40) | \ |
249 | ((u_int64_t)(((const u_char *)(p))[3]) << 32) | \ |
250 | ((u_int64_t)(((const u_char *)(p))[4]) << 24) | \ |
251 | ((u_int64_t)(((const u_char *)(p))[5]) << 16) | \ |
252 | ((u_int64_t)(((const u_char *)(p))[6]) << 8) | \ |
253 | (u_int64_t)(((const u_char *)(p))[7])) |
254 | #define PEEK_U32(p) \ |
255 | (((u_int32_t)(((const u_char *)(p))[0]) << 24) | \ |
256 | ((u_int32_t)(((const u_char *)(p))[1]) << 16) | \ |
257 | ((u_int32_t)(((const u_char *)(p))[2]) << 8) | \ |
258 | (u_int32_t)(((const u_char *)(p))[3])) |
259 | #define PEEK_U16(p) \ |
260 | (((u_int16_t)(((const u_char *)(p))[0]) << 8) | \ |
261 | (u_int16_t)(((const u_char *)(p))[1])) |
262 | |
263 | #define POKE_U64(p, v) \ |
264 | do { \ |
265 | const u_int64_t __v = (v); \ |
266 | ((u_char *)(p))[0] = (__v >> 56) & 0xff; \ |
267 | ((u_char *)(p))[1] = (__v >> 48) & 0xff; \ |
268 | ((u_char *)(p))[2] = (__v >> 40) & 0xff; \ |
269 | ((u_char *)(p))[3] = (__v >> 32) & 0xff; \ |
270 | ((u_char *)(p))[4] = (__v >> 24) & 0xff; \ |
271 | ((u_char *)(p))[5] = (__v >> 16) & 0xff; \ |
272 | ((u_char *)(p))[6] = (__v >> 8) & 0xff; \ |
273 | ((u_char *)(p))[7] = __v & 0xff; \ |
274 | } while (0) |
275 | #define POKE_U32(p, v) \ |
276 | do { \ |
277 | const u_int32_t __v = (v); \ |
278 | ((u_char *)(p))[0] = (__v >> 24) & 0xff; \ |
279 | ((u_char *)(p))[1] = (__v >> 16) & 0xff; \ |
280 | ((u_char *)(p))[2] = (__v >> 8) & 0xff; \ |
281 | ((u_char *)(p))[3] = __v & 0xff; \ |
282 | } while (0) |
283 | #define POKE_U16(p, v) \ |
284 | do { \ |
285 | const u_int16_t __v = (v); \ |
286 | ((u_char *)(p))[0] = (__v >> 8) & 0xff; \ |
287 | ((u_char *)(p))[1] = __v & 0xff; \ |
288 | } while (0) |
289 | |
290 | /* Internal definitions follow. Exposed for regress tests */ |
291 | #ifdef SSHBUF_INTERNAL |
292 | |
293 | /* |
294 | * Return the allocation size of buf |
295 | */ |
296 | size_t sshbuf_alloc(const struct sshbuf *buf); |
297 | |
298 | /* |
299 | * Increment the reference count of buf. |
300 | */ |
301 | int sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent); |
302 | |
303 | /* |
304 | * Return the parent buffer of buf, or NULL if it has no parent. |
305 | */ |
306 | const struct sshbuf *sshbuf_parent(const struct sshbuf *buf); |
307 | |
308 | /* |
309 | * Return the reference count of buf |
310 | */ |
311 | u_int sshbuf_refcount(const struct sshbuf *buf); |
312 | |
313 | # define SSHBUF_SIZE_INIT 256 /* Initial allocation */ |
314 | # define SSHBUF_SIZE_INC 256 /* Preferred increment length */ |
315 | # define SSHBUF_PACK_MIN 8192 /* Minimim packable offset */ |
316 | |
317 | /* # define SSHBUF_ABORT abort */ |
318 | /* # define SSHBUF_DEBUG */ |
319 | |
320 | # ifndef SSHBUF_ABORT |
321 | # define SSHBUF_ABORT() |
322 | # endif |
323 | |
324 | # ifdef SSHBUF_DEBUG |
325 | # define SSHBUF_TELL(what) do { \ |
326 | printf("%s:%d %s: %s size %zu alloc %zu off %zu max %zu\n", \ |
327 | __FILE__, __LINE__, __func__, what, \ |
328 | buf->size, buf->alloc, buf->off, buf->max_size); \ |
329 | fflush(stdout); \ |
330 | } while (0) |
331 | # define SSHBUF_DBG(x) do { \ |
332 | printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ |
333 | printf x; \ |
334 | printf("\n"); \ |
335 | fflush(stdout); \ |
336 | } while (0) |
337 | # else |
338 | # define SSHBUF_TELL(what) |
339 | # define SSHBUF_DBG(x) |
340 | # endif |
341 | #endif /* SSHBUF_INTERNAL */ |
342 | |
343 | #endif /* _SSHBUF_H */ |
344 | |