1/* 2 * Copyright 2015-2018 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 16int 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 26int 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 40int 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 71int 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 82static 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 90static 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 118int 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 134int 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 147int WPACKET_init(WPACKET *pkt, BUF_MEM *buf) 148{ 149 return WPACKET_init_len(pkt, buf, 0); 150} 151 152int 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| */ 164static int put_value(unsigned char *data, size_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 */ 186static 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 225int 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 240int 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 252int 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 272int 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 304int WPACKET_start_sub_packet(WPACKET *pkt) 305{ 306 return WPACKET_start_sub_packet_len__(pkt, 0); 307} 308 309int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size) 310{ 311 unsigned char *data; 312 313 /* Internal API, so should not fail */ 314 if (!ossl_assert(size <= sizeof(unsigned int)) 315 || !WPACKET_allocate_bytes(pkt, size, &data) 316 || !put_value(data, val, size)) 317 return 0; 318 319 return 1; 320} 321 322int 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 347int 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 362int 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 377int 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 388int 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 399int 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 410unsigned char *WPACKET_get_curr(WPACKET *pkt) 411{ 412 return GETBUF(pkt) + pkt->curr; 413} 414 415void 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