1/* Copyright (c) 2014, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15#include <stdio.h> 16#include <stdlib.h> 17 18#include <openssl/crypto.h> 19#include <openssl/bytestring.h> 20 21#include "internal.h" 22 23 24static int test_skip(void) { 25 static const uint8_t kData[] = {1, 2, 3}; 26 CBS data; 27 28 CBS_init(&data, kData, sizeof(kData)); 29 return CBS_len(&data) == 3 && 30 CBS_skip(&data, 1) && 31 CBS_len(&data) == 2 && 32 CBS_skip(&data, 2) && 33 CBS_len(&data) == 0 && 34 !CBS_skip(&data, 1); 35} 36 37static int test_get_u(void) { 38 static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 39 uint8_t u8; 40 uint16_t u16; 41 uint32_t u32; 42 CBS data; 43 44 CBS_init(&data, kData, sizeof(kData)); 45 return CBS_get_u8(&data, &u8) && 46 u8 == 1 && 47 CBS_get_u16(&data, &u16) && 48 u16 == 0x203 && 49 CBS_get_u24(&data, &u32) && 50 u32 == 0x40506 && 51 CBS_get_u32(&data, &u32) && 52 u32 == 0x708090a && 53 !CBS_get_u8(&data, &u8); 54} 55 56static int test_get_prefixed(void) { 57 static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1}; 58 uint8_t u8; 59 uint16_t u16; 60 uint32_t u32; 61 CBS data, prefixed; 62 63 CBS_init(&data, kData, sizeof(kData)); 64 return CBS_get_u8_length_prefixed(&data, &prefixed) && 65 CBS_len(&prefixed) == 1 && 66 CBS_get_u8(&prefixed, &u8) && 67 u8 == 2 && 68 CBS_get_u16_length_prefixed(&data, &prefixed) && 69 CBS_len(&prefixed) == 2 && 70 CBS_get_u16(&prefixed, &u16) && 71 u16 == 0x304 && 72 CBS_get_u24_length_prefixed(&data, &prefixed) && 73 CBS_len(&prefixed) == 3 && 74 CBS_get_u24(&prefixed, &u32) && 75 u32 == 0x30201; 76} 77 78static int test_get_prefixed_bad(void) { 79 static const uint8_t kData1[] = {2, 1}; 80 static const uint8_t kData2[] = {0, 2, 1}; 81 static const uint8_t kData3[] = {0, 0, 2, 1}; 82 CBS data, prefixed; 83 84 CBS_init(&data, kData1, sizeof(kData1)); 85 if (CBS_get_u8_length_prefixed(&data, &prefixed)) { 86 return 0; 87 } 88 89 CBS_init(&data, kData2, sizeof(kData2)); 90 if (CBS_get_u16_length_prefixed(&data, &prefixed)) { 91 return 0; 92 } 93 94 CBS_init(&data, kData3, sizeof(kData3)); 95 if (CBS_get_u24_length_prefixed(&data, &prefixed)) { 96 return 0; 97 } 98 99 return 1; 100} 101 102static int test_get_asn1(void) { 103 static const uint8_t kData1[] = {0x30, 2, 1, 2}; 104 static const uint8_t kData2[] = {0x30, 3, 1, 2}; 105 static const uint8_t kData3[] = {0x30, 0x80}; 106 static const uint8_t kData4[] = {0x30, 0x81, 1, 1}; 107 static const uint8_t kData5[] = {0x30, 0x82, 0, 1, 1}; 108 109 CBS data, contents; 110 111 CBS_init(&data, kData1, sizeof(kData1)); 112 if (!CBS_get_asn1(&data, &contents, 0x30) || 113 CBS_len(&contents) != 2 || 114 memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) { 115 return 0; 116 } 117 118 CBS_init(&data, kData2, sizeof(kData2)); 119 /* data is truncated */ 120 if (CBS_get_asn1(&data, &contents, 0x30)) { 121 return 0; 122 } 123 124 CBS_init(&data, kData3, sizeof(kData3)); 125 /* zero byte length of length */ 126 if (CBS_get_asn1(&data, &contents, 0x30)) { 127 return 0; 128 } 129 130 CBS_init(&data, kData4, sizeof(kData4)); 131 /* long form mistakenly used. */ 132 if (CBS_get_asn1(&data, &contents, 0x30)) { 133 return 0; 134 } 135 136 CBS_init(&data, kData5, sizeof(kData5)); 137 /* length takes too many bytes. */ 138 if (CBS_get_asn1(&data, &contents, 0x30)) { 139 return 0; 140 } 141 142 CBS_init(&data, kData1, sizeof(kData1)); 143 /* wrong tag. */ 144 if (CBS_get_asn1(&data, &contents, 0x31)) { 145 return 0; 146 } 147 148 return 1; 149} 150 151static int test_cbb_basic(void) { 152 static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8}; 153 uint8_t *buf; 154 size_t buf_len; 155 int ok; 156 CBB cbb; 157 158 if (!CBB_init(&cbb, 100)) { 159 return 0; 160 } 161 CBB_cleanup(&cbb); 162 163 if (!CBB_init(&cbb, 0) || 164 !CBB_add_u8(&cbb, 1) || 165 !CBB_add_u16(&cbb, 0x203) || 166 !CBB_add_u24(&cbb, 0x40506) || 167 !CBB_add_bytes(&cbb, (const uint8_t*) "\x07\x08", 2) || 168 !CBB_finish(&cbb, &buf, &buf_len)) { 169 return 0; 170 } 171 172 ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; 173 free(buf); 174 return ok; 175} 176 177static int test_cbb_fixed(void) { 178 CBB cbb; 179 uint8_t buf[1]; 180 uint8_t *out_buf; 181 size_t out_size; 182 183 if (!CBB_init_fixed(&cbb, NULL, 0) || 184 CBB_add_u8(&cbb, 1) || 185 !CBB_finish(&cbb, &out_buf, &out_size) || 186 out_buf != NULL || 187 out_size != 0) { 188 return 0; 189 } 190 191 if (!CBB_init_fixed(&cbb, buf, 1) || 192 !CBB_add_u8(&cbb, 1) || 193 CBB_add_u8(&cbb, 2) || 194 !CBB_finish(&cbb, &out_buf, &out_size) || 195 out_buf != buf || 196 out_size != 1 || 197 buf[0] != 1) { 198 return 0; 199 } 200 201 return 1; 202} 203 204static int test_cbb_finish_child(void) { 205 CBB cbb, child; 206 uint8_t *out_buf; 207 size_t out_size; 208 209 if (!CBB_init(&cbb, 16) || 210 !CBB_add_u8_length_prefixed(&cbb, &child) || 211 CBB_finish(&child, &out_buf, &out_size) || 212 !CBB_finish(&cbb, &out_buf, &out_size) || 213 out_size != 1 || 214 out_buf[0] != 0) { 215 return 0; 216 } 217 218 free(out_buf); 219 return 1; 220} 221 222static int test_cbb_prefixed(void) { 223 static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3, 224 4, 5, 6, 5, 4, 1, 0, 1, 2}; 225 uint8_t *buf; 226 size_t buf_len; 227 CBB cbb, contents, inner_contents, inner_inner_contents; 228 int ok; 229 230 if (!CBB_init(&cbb, 0) || 231 !CBB_add_u8_length_prefixed(&cbb, &contents) || 232 !CBB_add_u8_length_prefixed(&cbb, &contents) || 233 !CBB_add_u8(&contents, 1) || 234 !CBB_add_u16_length_prefixed(&cbb, &contents) || 235 !CBB_add_u16(&contents, 0x203) || 236 !CBB_add_u24_length_prefixed(&cbb, &contents) || 237 !CBB_add_u24(&contents, 0x40506) || 238 !CBB_add_u8_length_prefixed(&cbb, &contents) || 239 !CBB_add_u8_length_prefixed(&contents, &inner_contents) || 240 !CBB_add_u8(&inner_contents, 1) || 241 !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) || 242 !CBB_add_u8(&inner_inner_contents, 2) || 243 !CBB_finish(&cbb, &buf, &buf_len)) { 244 return 0; 245 } 246 247 ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; 248 free(buf); 249 return ok; 250} 251 252static int test_cbb_misuse(void) { 253 CBB cbb, child, contents; 254 uint8_t *buf; 255 size_t buf_len; 256 257 if (!CBB_init(&cbb, 0) || 258 !CBB_add_u8_length_prefixed(&cbb, &child) || 259 !CBB_add_u8(&child, 1) || 260 !CBB_add_u8(&cbb, 2)) { 261 return 0; 262 } 263 264 /* Since we wrote to |cbb|, |child| is now invalid and attempts to write to 265 * it should fail. */ 266 if (CBB_add_u8(&child, 1) || 267 CBB_add_u16(&child, 1) || 268 CBB_add_u24(&child, 1) || 269 CBB_add_u8_length_prefixed(&child, &contents) || 270 CBB_add_u16_length_prefixed(&child, &contents) || 271 CBB_add_asn1(&child, &contents, 1) || 272 CBB_add_bytes(&child, (const uint8_t*) "a", 1)) { 273 fprintf(stderr, "CBB operation on invalid CBB did not fail.\n"); 274 return 0; 275 } 276 277 if (!CBB_finish(&cbb, &buf, &buf_len) || 278 buf_len != 3 || 279 memcmp(buf, "\x01\x01\x02", 3) != 0) { 280 return 0; 281 } 282 283 free(buf); 284 285 return 1; 286} 287 288static int test_cbb_asn1(void) { 289 static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3}; 290 uint8_t *buf, *test_data; 291 size_t buf_len; 292 CBB cbb, contents, inner_contents; 293 294 if (!CBB_init(&cbb, 0) || 295 !CBB_add_asn1(&cbb, &contents, 0x30) || 296 !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) || 297 !CBB_finish(&cbb, &buf, &buf_len)) { 298 return 0; 299 } 300 301 if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) { 302 return 0; 303 } 304 free(buf); 305 306 test_data = malloc(100000); 307 memset(test_data, 0x42, 100000); 308 309 if (!CBB_init(&cbb, 0) || 310 !CBB_add_asn1(&cbb, &contents, 0x30) || 311 !CBB_add_bytes(&contents, test_data, 130) || 312 !CBB_finish(&cbb, &buf, &buf_len)) { 313 return 0; 314 } 315 316 if (buf_len != 3 + 130 || 317 memcmp(buf, "\x30\x81\x82", 3) != 0 || 318 memcmp(buf + 3, test_data, 130) != 0) { 319 return 0; 320 } 321 free(buf); 322 323 if (!CBB_init(&cbb, 0) || 324 !CBB_add_asn1(&cbb, &contents, 0x30) || 325 !CBB_add_bytes(&contents, test_data, 1000) || 326 !CBB_finish(&cbb, &buf, &buf_len)) { 327 return 0; 328 } 329 330 if (buf_len != 4 + 1000 || 331 memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 || 332 memcmp(buf + 4, test_data, 1000)) { 333 return 0; 334 } 335 free(buf); 336 337 if (!CBB_init(&cbb, 0) || 338 !CBB_add_asn1(&cbb, &contents, 0x30) || 339 !CBB_add_asn1(&contents, &inner_contents, 0x30) || 340 !CBB_add_bytes(&inner_contents, test_data, 100000) || 341 !CBB_finish(&cbb, &buf, &buf_len)) { 342 return 0; 343 } 344 345 if (buf_len != 5 + 5 + 100000 || 346 memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 || 347 memcmp(buf + 10, test_data, 100000)) { 348 return 0; 349 } 350 free(buf); 351 352 free(test_data); 353 return 1; 354} 355 356static int do_ber_convert(const char *name, 357 const uint8_t *der_expected, size_t der_len, 358 const uint8_t *ber, size_t ber_len) { 359 CBS in; 360 uint8_t *out; 361 size_t out_len; 362 363 CBS_init(&in, ber, ber_len); 364 if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) { 365 fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name); 366 return 0; 367 } 368 369 if (out == NULL) { 370 if (ber_len != der_len || 371 memcmp(der_expected, ber, ber_len) != 0) { 372 fprintf(stderr, "%s: incorrect unconverted result.\n", name); 373 return 0; 374 } 375 376 return 1; 377 } 378 379 if (out_len != der_len || 380 memcmp(out, der_expected, der_len) != 0) { 381 fprintf(stderr, "%s: incorrect converted result.\n", name); 382 return 0; 383 } 384 385 free(out); 386 return 1; 387} 388 389static int test_ber_convert(void) { 390 static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00}; 391 392 /* kIndefBER contains a SEQUENCE with an indefinite length. */ 393 static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00}; 394 static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02}; 395 396 /* kOctetStringBER contains an indefinite length OCTETSTRING with two parts. 397 * These parts need to be concatenated in DER form. */ 398 static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1, 399 0x04, 0x02, 2, 3, 0x00, 0x00}; 400 static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3}; 401 402 /* kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite 403 * length elements extensively. */ 404 static const uint8_t kNSSBER[] = { 405 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 406 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x04, 407 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 408 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 409 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 410 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 411 0x10, 0x38, 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 412 0xf0, 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00, 413 }; 414 415 static const uint8_t kNSSDER[] = { 416 0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86, 417 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04, 418 0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06, 419 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84, 420 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8, 421 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38, 422 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0, 423 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, 424 }; 425 426 return do_ber_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER), 427 kSimpleBER, sizeof(kSimpleBER)) && 428 do_ber_convert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER, 429 sizeof(kIndefBER)) && 430 do_ber_convert("kOctetStringBER", kOctetStringDER, 431 sizeof(kOctetStringDER), kOctetStringBER, 432 sizeof(kOctetStringBER)) && 433 do_ber_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER, 434 sizeof(kNSSBER)); 435} 436 437int main(void) { 438 CRYPTO_library_init(); 439 440 if (!test_skip() || 441 !test_get_u() || 442 !test_get_prefixed() || 443 !test_get_prefixed_bad() || 444 !test_get_asn1() || 445 !test_cbb_basic() || 446 !test_cbb_fixed() || 447 !test_cbb_finish_child() || 448 !test_cbb_misuse() || 449 !test_cbb_prefixed() || 450 !test_cbb_asn1() || 451 !test_ber_convert()) { 452 return 1; 453 } 454 455 printf("PASS\n"); 456 return 0; 457} 458