1 /* 2 * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "internal/cryptlib.h" 11 #include "packet_local.h" 12 #include <openssl/sslerr.h> 13 14 #define DEFAULT_BUF_SIZE 256 15 16 int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) 17 { 18 if (!WPACKET_reserve_bytes(pkt, len, allocbytes)) 19 return 0; 20 21 pkt->written += len; 22 pkt->curr += len; 23 return 1; 24 } 25 26 int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len, 27 unsigned char **allocbytes, size_t lenbytes) 28 { 29 if (!WPACKET_start_sub_packet_len__(pkt, lenbytes) 30 || !WPACKET_allocate_bytes(pkt, len, allocbytes) 31 || !WPACKET_close(pkt)) 32 return 0; 33 34 return 1; 35 } 36 37 #define GETBUF(p) (((p)->staticbuf != NULL) \ 38 ? (p)->staticbuf : (unsigned char *)(p)->buf->data) 39 40 int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) 41 { 42 /* Internal API, so should not fail */ 43 if (!ossl_assert(pkt->subs != NULL && len != 0)) 44 return 0; 45 46 if (pkt->maxsize - pkt->written < len) 47 return 0; 48 49 if (pkt->staticbuf == NULL && (pkt->buf->length - pkt->written < len)) { 50 size_t newlen; 51 size_t reflen; 52 53 reflen = (len > pkt->buf->length) ? len : pkt->buf->length; 54 55 if (reflen > SIZE_MAX / 2) { 56 newlen = SIZE_MAX; 57 } else { 58 newlen = reflen * 2; 59 if (newlen < DEFAULT_BUF_SIZE) 60 newlen = DEFAULT_BUF_SIZE; 61 } 62 if (BUF_MEM_grow(pkt->buf, newlen) == 0) 63 return 0; 64 } 65 if (allocbytes != NULL) 66 *allocbytes = WPACKET_get_curr(pkt); 67 68 return 1; 69 } 70 71 int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, 72 unsigned char **allocbytes, size_t lenbytes) 73 { 74 if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes)) 75 return 0; 76 77 *allocbytes += lenbytes; 78 79 return 1; 80 } 81 82 static size_t maxmaxsize(size_t lenbytes) 83 { 84 if (lenbytes >= sizeof(size_t) || lenbytes == 0) 85 return SIZE_MAX; 86 87 return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes; 88 } 89 90 static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes) 91 { 92 unsigned char *lenchars; 93 94 pkt->curr = 0; 95 pkt->written = 0; 96 97 if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) { 98 SSLerr(SSL_F_WPACKET_INTERN_INIT_LEN, ERR_R_MALLOC_FAILURE); 99 return 0; 100 } 101 102 if (lenbytes == 0) 103 return 1; 104 105 pkt->subs->pwritten = lenbytes; 106 pkt->subs->lenbytes = lenbytes; 107 108 if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) { 109 OPENSSL_free(pkt->subs); 110 pkt->subs = NULL; 111 return 0; 112 } 113 pkt->subs->packet_len = lenchars - GETBUF(pkt); 114 115 return 1; 116 } 117 118 int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len, 119 size_t lenbytes) 120 { 121 size_t max = maxmaxsize(lenbytes); 122 123 /* Internal API, so should not fail */ 124 if (!ossl_assert(buf != NULL && len > 0)) 125 return 0; 126 127 pkt->staticbuf = buf; 128 pkt->buf = NULL; 129 pkt->maxsize = (max < len) ? max : len; 130 131 return wpacket_intern_init_len(pkt, lenbytes); 132 } 133 134 int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes) 135 { 136 /* Internal API, so should not fail */ 137 if (!ossl_assert(buf != NULL)) 138 return 0; 139 140 pkt->staticbuf = NULL; 141 pkt->buf = buf; 142 pkt->maxsize = maxmaxsize(lenbytes); 143 144 return wpacket_intern_init_len(pkt, lenbytes); 145 } 146 147 int WPACKET_init(WPACKET *pkt, BUF_MEM *buf) 148 { 149 return WPACKET_init_len(pkt, buf, 0); 150 } 151 152 int WPACKET_set_flags(WPACKET *pkt, unsigned int flags) 153 { 154 /* Internal API, so should not fail */ 155 if (!ossl_assert(pkt->subs != NULL)) 156 return 0; 157 158 pkt->subs->flags = flags; 159 160 return 1; 161 } 162 163 /* Store the |value| of length |len| at location |data| */ 164 static int put_value(unsigned char *data, uint64_t value, size_t len) 165 { 166 for (data += len - 1; len > 0; len--) { 167 *data = (unsigned char)(value & 0xff); 168 data--; 169 value >>= 8; 170 } 171 172 /* Check whether we could fit the value in the assigned number of bytes */ 173 if (value > 0) 174 return 0; 175 176 return 1; 177 } 178 179 180 /* 181 * Internal helper function used by WPACKET_close(), WPACKET_finish() and 182 * WPACKET_fill_lengths() to close a sub-packet and write out its length if 183 * necessary. If |doclose| is 0 then it goes through the motions of closing 184 * (i.e. it fills in all the lengths), but doesn't actually close anything. 185 */ 186 static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose) 187 { 188 size_t packlen = pkt->written - sub->pwritten; 189 190 if (packlen == 0 191 && (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0) 192 return 0; 193 194 if (packlen == 0 195 && sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) { 196 /* We can't handle this case. Return an error */ 197 if (!doclose) 198 return 0; 199 200 /* Deallocate any bytes allocated for the length of the WPACKET */ 201 if ((pkt->curr - sub->lenbytes) == sub->packet_len) { 202 pkt->written -= sub->lenbytes; 203 pkt->curr -= sub->lenbytes; 204 } 205 206 /* Don't write out the packet length */ 207 sub->packet_len = 0; 208 sub->lenbytes = 0; 209 } 210 211 /* Write out the WPACKET length if needed */ 212 if (sub->lenbytes > 0 213 && !put_value(&GETBUF(pkt)[sub->packet_len], packlen, 214 sub->lenbytes)) 215 return 0; 216 217 if (doclose) { 218 pkt->subs = sub->parent; 219 OPENSSL_free(sub); 220 } 221 222 return 1; 223 } 224 225 int WPACKET_fill_lengths(WPACKET *pkt) 226 { 227 WPACKET_SUB *sub; 228 229 if (!ossl_assert(pkt->subs != NULL)) 230 return 0; 231 232 for (sub = pkt->subs; sub != NULL; sub = sub->parent) { 233 if (!wpacket_intern_close(pkt, sub, 0)) 234 return 0; 235 } 236 237 return 1; 238 } 239 240 int WPACKET_close(WPACKET *pkt) 241 { 242 /* 243 * Internal API, so should not fail - but we do negative testing of this 244 * so no assert (otherwise the tests fail) 245 */ 246 if (pkt->subs == NULL || pkt->subs->parent == NULL) 247 return 0; 248 249 return wpacket_intern_close(pkt, pkt->subs, 1); 250 } 251 252 int WPACKET_finish(WPACKET *pkt) 253 { 254 int ret; 255 256 /* 257 * Internal API, so should not fail - but we do negative testing of this 258 * so no assert (otherwise the tests fail) 259 */ 260 if (pkt->subs == NULL || pkt->subs->parent != NULL) 261 return 0; 262 263 ret = wpacket_intern_close(pkt, pkt->subs, 1); 264 if (ret) { 265 OPENSSL_free(pkt->subs); 266 pkt->subs = NULL; 267 } 268 269 return ret; 270 } 271 272 int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes) 273 { 274 WPACKET_SUB *sub; 275 unsigned char *lenchars; 276 277 /* Internal API, so should not fail */ 278 if (!ossl_assert(pkt->subs != NULL)) 279 return 0; 280 281 if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) { 282 SSLerr(SSL_F_WPACKET_START_SUB_PACKET_LEN__, ERR_R_MALLOC_FAILURE); 283 return 0; 284 } 285 286 sub->parent = pkt->subs; 287 pkt->subs = sub; 288 sub->pwritten = pkt->written + lenbytes; 289 sub->lenbytes = lenbytes; 290 291 if (lenbytes == 0) { 292 sub->packet_len = 0; 293 return 1; 294 } 295 296 if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) 297 return 0; 298 /* Convert to an offset in case the underlying BUF_MEM gets realloc'd */ 299 sub->packet_len = lenchars - GETBUF(pkt); 300 301 return 1; 302 } 303 304 int WPACKET_start_sub_packet(WPACKET *pkt) 305 { 306 return WPACKET_start_sub_packet_len__(pkt, 0); 307 } 308 309 int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t size) 310 { 311 unsigned char *data; 312 313 /* Internal API, so should not fail */ 314 if (!ossl_assert(size <= sizeof(uint64_t)) 315 || !WPACKET_allocate_bytes(pkt, size, &data) 316 || !put_value(data, val, size)) 317 return 0; 318 319 return 1; 320 } 321 322 int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize) 323 { 324 WPACKET_SUB *sub; 325 size_t lenbytes; 326 327 /* Internal API, so should not fail */ 328 if (!ossl_assert(pkt->subs != NULL)) 329 return 0; 330 331 /* Find the WPACKET_SUB for the top level */ 332 for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent) 333 continue; 334 335 lenbytes = sub->lenbytes; 336 if (lenbytes == 0) 337 lenbytes = sizeof(pkt->maxsize); 338 339 if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written) 340 return 0; 341 342 pkt->maxsize = maxsize; 343 344 return 1; 345 } 346 347 int WPACKET_memset(WPACKET *pkt, int ch, size_t len) 348 { 349 unsigned char *dest; 350 351 if (len == 0) 352 return 1; 353 354 if (!WPACKET_allocate_bytes(pkt, len, &dest)) 355 return 0; 356 357 memset(dest, ch, len); 358 359 return 1; 360 } 361 362 int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len) 363 { 364 unsigned char *dest; 365 366 if (len == 0) 367 return 1; 368 369 if (!WPACKET_allocate_bytes(pkt, len, &dest)) 370 return 0; 371 372 memcpy(dest, src, len); 373 374 return 1; 375 } 376 377 int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len, 378 size_t lenbytes) 379 { 380 if (!WPACKET_start_sub_packet_len__(pkt, lenbytes) 381 || !WPACKET_memcpy(pkt, src, len) 382 || !WPACKET_close(pkt)) 383 return 0; 384 385 return 1; 386 } 387 388 int WPACKET_get_total_written(WPACKET *pkt, size_t *written) 389 { 390 /* Internal API, so should not fail */ 391 if (!ossl_assert(written != NULL)) 392 return 0; 393 394 *written = pkt->written; 395 396 return 1; 397 } 398 399 int WPACKET_get_length(WPACKET *pkt, size_t *len) 400 { 401 /* Internal API, so should not fail */ 402 if (!ossl_assert(pkt->subs != NULL && len != NULL)) 403 return 0; 404 405 *len = pkt->written - pkt->subs->pwritten; 406 407 return 1; 408 } 409 410 unsigned char *WPACKET_get_curr(WPACKET *pkt) 411 { 412 return GETBUF(pkt) + pkt->curr; 413 } 414 415 void WPACKET_cleanup(WPACKET *pkt) 416 { 417 WPACKET_SUB *sub, *parent; 418 419 for (sub = pkt->subs; sub != NULL; sub = parent) { 420 parent = sub->parent; 421 OPENSSL_free(sub); 422 } 423 pkt->subs = NULL; 424 } 425