1 /* 2 * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (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 <string.h> 11 #include <openssl/buffer.h> 12 #include <openssl/rand.h> 13 #include "internal/packet.h" 14 #include "testutil.h" 15 16 static const unsigned char simple1[] = { 0xff }; 17 static const unsigned char simple2[] = { 0x01, 0xff }; 18 static const unsigned char simple3[] = { 0x00, 0x00, 0x00, 0x01, 0xff }; 19 static const unsigned char nestedsub[] = { 0x03, 0xff, 0x01, 0xff }; 20 static const unsigned char seqsub[] = { 0x01, 0xff, 0x01, 0xff }; 21 static const unsigned char empty[] = { 0x00 }; 22 static const unsigned char alloc[] = { 0x02, 0xfe, 0xff }; 23 static const unsigned char submem[] = { 0x03, 0x02, 0xfe, 0xff }; 24 static const unsigned char fixed[] = { 0xff, 0xff, 0xff }; 25 static const unsigned char simpleder[] = { 26 0xfc, 0x04, 0x00, 0x01, 0x02, 0x03, 0xff, 0xfe, 0xfd 27 }; 28 29 static BUF_MEM *buf; 30 31 static int cleanup(WPACKET *pkt) 32 { 33 WPACKET_cleanup(pkt); 34 return 0; 35 } 36 37 static int test_WPACKET_init(void) 38 { 39 WPACKET pkt; 40 int i; 41 size_t written; 42 unsigned char sbuf[3]; 43 44 if (!TEST_true(WPACKET_init(&pkt, buf)) 45 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 46 /* Closing a top level WPACKET should fail */ 47 || !TEST_false(WPACKET_close(&pkt)) 48 /* Finishing a top level WPACKET should succeed */ 49 || !TEST_true(WPACKET_finish(&pkt)) 50 /* 51 * Can't call close or finish on a WPACKET that's already 52 * finished. 53 */ 54 || !TEST_false(WPACKET_close(&pkt)) 55 || !TEST_false(WPACKET_finish(&pkt)) 56 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 57 || !TEST_mem_eq(buf->data, written, simple1, sizeof(simple1))) 58 return cleanup(&pkt); 59 60 /* Now try with a one byte length prefix */ 61 if (!TEST_true(WPACKET_init_len(&pkt, buf, 1)) 62 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 63 || !TEST_true(WPACKET_finish(&pkt)) 64 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 65 || !TEST_mem_eq(buf->data, written, simple2, sizeof(simple2))) 66 return cleanup(&pkt); 67 68 /* And a longer length prefix */ 69 if (!TEST_true(WPACKET_init_len(&pkt, buf, 4)) 70 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 71 || !TEST_true(WPACKET_finish(&pkt)) 72 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 73 || !TEST_mem_eq(buf->data, written, simple3, sizeof(simple3))) 74 return cleanup(&pkt); 75 76 if (!TEST_true(WPACKET_init_len(&pkt, buf, 1))) 77 return cleanup(&pkt); 78 for (i = 1; i < 257; i++) { 79 /* 80 * Putting more bytes in than fit for the size of the length prefix 81 * should fail 82 */ 83 if (!TEST_int_eq(WPACKET_put_bytes_u8(&pkt, 0xff), i < 256)) 84 return cleanup(&pkt); 85 } 86 if (!TEST_true(WPACKET_finish(&pkt))) 87 return cleanup(&pkt); 88 89 /* Test initialising from a fixed size buffer */ 90 if (!TEST_true(WPACKET_init_static_len(&pkt, sbuf, sizeof(sbuf), 0)) 91 /* Adding 3 bytes should succeed */ 92 || !TEST_true(WPACKET_put_bytes_u24(&pkt, 0xffffff)) 93 /* Adding 1 more byte should fail */ 94 || !TEST_false(WPACKET_put_bytes_u8(&pkt, 0xff)) 95 /* Finishing the top level WPACKET should succeed */ 96 || !TEST_true(WPACKET_finish(&pkt)) 97 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 98 || !TEST_mem_eq(sbuf, written, fixed, sizeof(sbuf)) 99 /* Initialise with 1 len byte */ 100 || !TEST_true(WPACKET_init_static_len(&pkt, sbuf, sizeof(sbuf), 1)) 101 /* Adding 2 bytes should succeed */ 102 || !TEST_true(WPACKET_put_bytes_u16(&pkt, 0xfeff)) 103 /* Adding 1 more byte should fail */ 104 || !TEST_false(WPACKET_put_bytes_u8(&pkt, 0xff)) 105 || !TEST_true(WPACKET_finish(&pkt)) 106 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 107 || !TEST_mem_eq(sbuf, written, alloc, sizeof(alloc))) 108 return cleanup(&pkt); 109 110 return 1; 111 } 112 113 static int test_WPACKET_set_max_size(void) 114 { 115 WPACKET pkt; 116 size_t written; 117 118 if (!TEST_true(WPACKET_init(&pkt, buf)) 119 /* 120 * No previous lenbytes set so we should be ok to set the max 121 * possible max size 122 */ 123 || !TEST_true(WPACKET_set_max_size(&pkt, SIZE_MAX)) 124 /* We should be able to set it smaller too */ 125 || !TEST_true(WPACKET_set_max_size(&pkt, SIZE_MAX -1)) 126 /* And setting it bigger again should be ok */ 127 || !TEST_true(WPACKET_set_max_size(&pkt, SIZE_MAX)) 128 || !TEST_true(WPACKET_finish(&pkt))) 129 return cleanup(&pkt); 130 131 if (!TEST_true(WPACKET_init_len(&pkt, buf, 1)) 132 /* 133 * Should fail because we already consumed 1 byte with the 134 * length 135 */ 136 || !TEST_false(WPACKET_set_max_size(&pkt, 0)) 137 /* 138 * Max size can't be bigger than biggest that will fit in 139 * lenbytes 140 */ 141 || !TEST_false(WPACKET_set_max_size(&pkt, 0x0101)) 142 /* It can be the same as the maximum possible size */ 143 || !TEST_true(WPACKET_set_max_size(&pkt, 0x0100)) 144 /* Or it can be less */ 145 || !TEST_true(WPACKET_set_max_size(&pkt, 0x01)) 146 /* Should fail because packet is already filled */ 147 || !TEST_false(WPACKET_put_bytes_u8(&pkt, 0xff)) 148 /* You can't put in more bytes than max size */ 149 || !TEST_true(WPACKET_set_max_size(&pkt, 0x02)) 150 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 151 || !TEST_false(WPACKET_put_bytes_u8(&pkt, 0xff)) 152 || !TEST_true(WPACKET_finish(&pkt)) 153 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 154 || !TEST_mem_eq(buf->data, written, simple2, sizeof(simple2))) 155 return cleanup(&pkt); 156 157 return 1; 158 } 159 160 static int test_WPACKET_start_sub_packet(void) 161 { 162 WPACKET pkt; 163 size_t written; 164 size_t len; 165 166 if (!TEST_true(WPACKET_init(&pkt, buf)) 167 || !TEST_true(WPACKET_start_sub_packet(&pkt)) 168 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 169 /* Can't finish because we have a sub packet */ 170 || !TEST_false(WPACKET_finish(&pkt)) 171 || !TEST_true(WPACKET_close(&pkt)) 172 /* Sub packet is closed so can't close again */ 173 || !TEST_false(WPACKET_close(&pkt)) 174 /* Now a top level so finish should succeed */ 175 || !TEST_true(WPACKET_finish(&pkt)) 176 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 177 || !TEST_mem_eq(buf->data, written, simple1, sizeof(simple1))) 178 return cleanup(&pkt); 179 180 /* Single sub-packet with length prefix */ 181 if (!TEST_true(WPACKET_init(&pkt, buf)) 182 || !TEST_true(WPACKET_start_sub_packet_u8(&pkt)) 183 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 184 || !TEST_true(WPACKET_close(&pkt)) 185 || !TEST_true(WPACKET_finish(&pkt)) 186 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 187 || !TEST_mem_eq(buf->data, written, simple2, sizeof(simple2))) 188 return cleanup(&pkt); 189 190 /* Nested sub-packets with length prefixes */ 191 if (!TEST_true(WPACKET_init(&pkt, buf)) 192 || !TEST_true(WPACKET_start_sub_packet_u8(&pkt)) 193 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 194 || !TEST_true(WPACKET_start_sub_packet_u8(&pkt)) 195 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 196 || !TEST_true(WPACKET_get_length(&pkt, &len)) 197 || !TEST_size_t_eq(len, 1) 198 || !TEST_true(WPACKET_close(&pkt)) 199 || !TEST_true(WPACKET_get_length(&pkt, &len)) 200 || !TEST_size_t_eq(len, 3) 201 || !TEST_true(WPACKET_close(&pkt)) 202 || !TEST_true(WPACKET_finish(&pkt)) 203 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 204 || !TEST_mem_eq(buf->data, written, nestedsub, sizeof(nestedsub))) 205 return cleanup(&pkt); 206 207 /* Sequential sub-packets with length prefixes */ 208 if (!TEST_true(WPACKET_init(&pkt, buf)) 209 || !TEST_true(WPACKET_start_sub_packet_u8(&pkt)) 210 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 211 || !TEST_true(WPACKET_close(&pkt)) 212 || !TEST_true(WPACKET_start_sub_packet_u8(&pkt)) 213 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 214 || !TEST_true(WPACKET_close(&pkt)) 215 || !TEST_true(WPACKET_finish(&pkt)) 216 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 217 || !TEST_mem_eq(buf->data, written, seqsub, sizeof(seqsub))) 218 return cleanup(&pkt); 219 220 /* Nested sub-packets with lengths filled before finish */ 221 if (!TEST_true(WPACKET_init(&pkt, buf)) 222 || !TEST_true(WPACKET_start_sub_packet_u8(&pkt)) 223 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 224 || !TEST_true(WPACKET_start_sub_packet_u8(&pkt)) 225 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 226 || !TEST_true(WPACKET_get_length(&pkt, &len)) 227 || !TEST_size_t_eq(len, 1) 228 || !TEST_true(WPACKET_close(&pkt)) 229 || !TEST_true(WPACKET_get_length(&pkt, &len)) 230 || !TEST_size_t_eq(len, 3) 231 || !TEST_true(WPACKET_close(&pkt)) 232 || !TEST_true(WPACKET_fill_lengths(&pkt)) 233 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 234 || !TEST_mem_eq(buf->data, written, nestedsub, sizeof(nestedsub)) 235 || !TEST_true(WPACKET_finish(&pkt))) 236 return cleanup(&pkt); 237 238 return 1; 239 } 240 241 242 static int test_WPACKET_set_flags(void) 243 { 244 WPACKET pkt; 245 size_t written; 246 247 /* Set packet to be non-zero length */ 248 if (!TEST_true(WPACKET_init(&pkt, buf)) 249 || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)) 250 /* Should fail because of zero length */ 251 || !TEST_false(WPACKET_finish(&pkt)) 252 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 253 || !TEST_true(WPACKET_finish(&pkt)) 254 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 255 || !TEST_mem_eq(buf->data, written, simple1, sizeof(simple1))) 256 return cleanup(&pkt); 257 258 /* Repeat above test in a sub-packet */ 259 if (!TEST_true(WPACKET_init(&pkt, buf)) 260 || !TEST_true(WPACKET_start_sub_packet(&pkt)) 261 || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)) 262 /* Should fail because of zero length */ 263 || !TEST_false(WPACKET_close(&pkt)) 264 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 265 || !TEST_true(WPACKET_close(&pkt)) 266 || !TEST_true(WPACKET_finish(&pkt)) 267 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 268 || !TEST_mem_eq(buf->data, written, simple1, sizeof(simple1))) 269 return cleanup(&pkt); 270 271 /* Set packet to abandon non-zero length */ 272 if (!TEST_true(WPACKET_init_len(&pkt, buf, 1)) 273 || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)) 274 || !TEST_true(WPACKET_finish(&pkt)) 275 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 276 || !TEST_size_t_eq(written, 0)) 277 return cleanup(&pkt); 278 279 /* Repeat above test but only abandon a sub-packet */ 280 if (!TEST_true(WPACKET_init_len(&pkt, buf, 1)) 281 || !TEST_true(WPACKET_start_sub_packet_u8(&pkt)) 282 || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)) 283 || !TEST_true(WPACKET_close(&pkt)) 284 || !TEST_true(WPACKET_finish(&pkt)) 285 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 286 || !TEST_mem_eq(buf->data, written, empty, sizeof(empty))) 287 return cleanup(&pkt); 288 289 /* And repeat with a non empty sub-packet */ 290 if (!TEST_true(WPACKET_init(&pkt, buf)) 291 || !TEST_true(WPACKET_start_sub_packet_u8(&pkt)) 292 || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)) 293 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff)) 294 || !TEST_true(WPACKET_close(&pkt)) 295 || !TEST_true(WPACKET_finish(&pkt)) 296 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 297 || !TEST_mem_eq(buf->data, written, simple2, sizeof(simple2))) 298 return cleanup(&pkt); 299 return 1; 300 } 301 302 static int test_WPACKET_allocate_bytes(void) 303 { 304 WPACKET pkt; 305 size_t written; 306 unsigned char *bytes; 307 308 if (!TEST_true(WPACKET_init_len(&pkt, buf, 1)) 309 || !TEST_true(WPACKET_allocate_bytes(&pkt, 2, &bytes))) 310 return cleanup(&pkt); 311 bytes[0] = 0xfe; 312 bytes[1] = 0xff; 313 if (!TEST_true(WPACKET_finish(&pkt)) 314 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 315 || !TEST_mem_eq(buf->data, written, alloc, sizeof(alloc))) 316 return cleanup(&pkt); 317 318 /* Repeat with WPACKET_sub_allocate_bytes */ 319 if (!TEST_true(WPACKET_init_len(&pkt, buf, 1)) 320 || !TEST_true(WPACKET_sub_allocate_bytes_u8(&pkt, 2, &bytes))) 321 return cleanup(&pkt); 322 bytes[0] = 0xfe; 323 bytes[1] = 0xff; 324 if (!TEST_true(WPACKET_finish(&pkt)) 325 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 326 || !TEST_mem_eq(buf->data, written, submem, sizeof(submem))) 327 return cleanup(&pkt); 328 329 return 1; 330 } 331 332 static int test_WPACKET_memcpy(void) 333 { 334 WPACKET pkt; 335 size_t written; 336 const unsigned char bytes[] = { 0xfe, 0xff }; 337 338 if (!TEST_true(WPACKET_init_len(&pkt, buf, 1)) 339 || !TEST_true(WPACKET_memcpy(&pkt, bytes, sizeof(bytes))) 340 || !TEST_true(WPACKET_finish(&pkt)) 341 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 342 || !TEST_mem_eq(buf->data, written, alloc, sizeof(alloc))) 343 return cleanup(&pkt); 344 345 /* Repeat with WPACKET_sub_memcpy() */ 346 if (!TEST_true(WPACKET_init_len(&pkt, buf, 1)) 347 || !TEST_true(WPACKET_sub_memcpy_u8(&pkt, bytes, sizeof(bytes))) 348 || !TEST_true(WPACKET_finish(&pkt)) 349 || !TEST_true(WPACKET_get_total_written(&pkt, &written)) 350 || !TEST_mem_eq(buf->data, written, submem, sizeof(submem))) 351 return cleanup(&pkt); 352 353 return 1; 354 } 355 356 static int test_WPACKET_init_der(void) 357 { 358 WPACKET pkt; 359 unsigned char sbuf[1024]; 360 unsigned char testdata[] = { 0x00, 0x01, 0x02, 0x03 }; 361 unsigned char testdata2[259] = { 0x82, 0x01, 0x00 }; 362 size_t written[2]; 363 size_t size1, size2; 364 int flags = WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH; 365 int i; 366 367 /* Test initialising for writing DER */ 368 if (!TEST_true(WPACKET_init_der(&pkt, sbuf, sizeof(sbuf))) 369 || !TEST_true(WPACKET_put_bytes_u24(&pkt, 0xfffefd)) 370 /* Test writing data in a length prefixed sub-packet */ 371 || !TEST_true(WPACKET_start_sub_packet(&pkt)) 372 || !TEST_true(WPACKET_memcpy(&pkt, testdata, sizeof(testdata))) 373 || !TEST_true(WPACKET_close(&pkt)) 374 || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xfc)) 375 /* this sub-packet is empty, and should render zero bytes */ 376 || (!TEST_true(WPACKET_start_sub_packet(&pkt)) 377 || !TEST_true(WPACKET_set_flags(&pkt, flags)) 378 || !TEST_true(WPACKET_get_total_written(&pkt, &size1)) 379 || !TEST_true(WPACKET_close(&pkt)) 380 || !TEST_true(WPACKET_get_total_written(&pkt, &size2)) 381 || !TEST_size_t_eq(size1, size2)) 382 || !TEST_true(WPACKET_finish(&pkt)) 383 || !TEST_true(WPACKET_get_total_written(&pkt, &written[0])) 384 || !TEST_mem_eq(WPACKET_get_curr(&pkt), written[0], simpleder, 385 sizeof(simpleder))) 386 return cleanup(&pkt); 387 388 /* Generate random packet data for test */ 389 if (!TEST_int_gt(RAND_bytes(&testdata2[3], sizeof(testdata2) - 3), 0)) 390 return 0; 391 392 /* 393 * Test with a sub-packet that has 2 length bytes. We do 2 passes - first 394 * with a NULL buffer, just to calculate lengths, and a second pass with a 395 * real buffer to actually generate a packet 396 */ 397 for (i = 0; i < 2; i++) { 398 if (i == 0) { 399 if (!TEST_true(WPACKET_init_null_der(&pkt))) 400 return 0; 401 } else { 402 if (!TEST_true(WPACKET_init_der(&pkt, sbuf, sizeof(sbuf)))) 403 return 0; 404 } 405 if (!TEST_true(WPACKET_start_sub_packet(&pkt)) 406 || !TEST_true(WPACKET_memcpy(&pkt, &testdata2[3], 407 sizeof(testdata2) - 3)) 408 || !TEST_true(WPACKET_close(&pkt)) 409 || !TEST_true(WPACKET_finish(&pkt)) 410 || !TEST_true(WPACKET_get_total_written(&pkt, &written[i]))) 411 return cleanup(&pkt); 412 } 413 414 /* 415 * Check that the size calculated in the first pass equals the size of the 416 * packet actually generated in the second pass. Also check the generated 417 * packet looks as we expect it to. 418 */ 419 if (!TEST_size_t_eq(written[0], written[1]) 420 || !TEST_mem_eq(WPACKET_get_curr(&pkt), written[1], testdata2, 421 sizeof(testdata2))) 422 return 0; 423 424 return 1; 425 } 426 427 int setup_tests(void) 428 { 429 if (!TEST_ptr(buf = BUF_MEM_new())) 430 return 0; 431 432 ADD_TEST(test_WPACKET_init); 433 ADD_TEST(test_WPACKET_set_max_size); 434 ADD_TEST(test_WPACKET_start_sub_packet); 435 ADD_TEST(test_WPACKET_set_flags); 436 ADD_TEST(test_WPACKET_allocate_bytes); 437 ADD_TEST(test_WPACKET_memcpy); 438 ADD_TEST(test_WPACKET_init_der); 439 return 1; 440 } 441 442 void cleanup_tests(void) 443 { 444 BUF_MEM_free(buf); 445 } 446