| 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 |  |