1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (c) 2014, Google Inc.
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Permission to use, copy, modify, and/or distribute this software for any
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * purpose with or without fee is hereby granted, provided that the above
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copyright notice and this permission notice appear in all copies.
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
154139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#if !defined(__STDC_CONSTANT_MACROS)
164139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#define __STDC_CONSTANT_MACROS
174139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#endif
184139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdio.h>
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdlib.h>
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h>
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
23e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <vector>
24e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
25f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/bytestring.h>
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/crypto.h>
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h"
29f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include "../internal.h"
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
32e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestSkip() {
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData[] = {1, 2, 3};
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS data;
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData, sizeof(kData));
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return CBS_len(&data) == 3 &&
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_skip(&data, 1) &&
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_len(&data) == 2 &&
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_skip(&data, 2) &&
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_len(&data) == 0 &&
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBS_skip(&data, 1);
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
45e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestGetUint() {
466e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t u8;
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint16_t u16;
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint32_t u32;
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS data;
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData, sizeof(kData));
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return CBS_get_u8(&data, &u8) &&
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    u8 == 1 &&
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_get_u16(&data, &u16) &&
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    u16 == 0x203 &&
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_get_u24(&data, &u32) &&
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    u32 == 0x40506 &&
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_get_u32(&data, &u32) &&
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    u32 == 0x708090a &&
616e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    CBS_get_last_u8(&data, &u8) &&
626e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    u8 == 0xb &&
636e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    !CBS_get_u8(&data, &u8) &&
646e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    !CBS_get_last_u8(&data, &u8);
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
67e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestGetPrefixed() {
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1};
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t u8;
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint16_t u16;
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint32_t u32;
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS data, prefixed;
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData, sizeof(kData));
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return CBS_get_u8_length_prefixed(&data, &prefixed) &&
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_len(&prefixed) == 1 &&
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_get_u8(&prefixed, &u8) &&
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    u8 == 2 &&
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_get_u16_length_prefixed(&data, &prefixed) &&
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_len(&prefixed) == 2 &&
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_get_u16(&prefixed, &u16) &&
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    u16 == 0x304 &&
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_get_u24_length_prefixed(&data, &prefixed) &&
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_len(&prefixed) == 3 &&
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_get_u24(&prefixed, &u32) &&
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    u32 == 0x30201;
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
89e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestGetPrefixedBad() {
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData1[] = {2, 1};
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData2[] = {0, 2, 1};
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData3[] = {0, 0, 2, 1};
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS data, prefixed;
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData1, sizeof(kData1));
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_u8_length_prefixed(&data, &prefixed)) {
97e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData2, sizeof(kData2));
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_u16_length_prefixed(&data, &prefixed)) {
102e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData3, sizeof(kData3));
106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_u24_length_prefixed(&data, &prefixed)) {
107e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
110e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
113e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestGetASN1() {
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData1[] = {0x30, 2, 1, 2};
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData2[] = {0x30, 3, 1, 2};
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData3[] = {0x30, 0x80};
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData4[] = {0x30, 0x81, 1, 1};
118b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  static const uint8_t kData5[4 + 0x80] = {0x30, 0x82, 0, 0x80};
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1};
120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1};
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1};
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff};
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS data, contents;
125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int present;
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint64_t value;
127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData1, sizeof(kData1));
129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_peek_asn1_tag(&data, 0x1) ||
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBS_peek_asn1_tag(&data, 0x30)) {
131e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBS_get_asn1(&data, &contents, 0x30) ||
134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_len(&contents) != 2 ||
13569939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
136e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData2, sizeof(kData2));
140e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // data is truncated
141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_asn1(&data, &contents, 0x30)) {
142e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData3, sizeof(kData3));
146e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // zero byte length of length
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_asn1(&data, &contents, 0x30)) {
148e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData4, sizeof(kData4));
152e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // long form mistakenly used.
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_asn1(&data, &contents, 0x30)) {
154e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData5, sizeof(kData5));
158e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // length takes too many bytes.
159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_asn1(&data, &contents, 0x30)) {
160e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData1, sizeof(kData1));
164e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // wrong tag.
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_asn1(&data, &contents, 0x31)) {
166e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, NULL, 0);
170e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // peek at empty data.
171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_peek_asn1_tag(&data, 0x30)) {
172e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, NULL, 0);
176e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // optional elements at empty data.
177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      present ||
179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      present ||
181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_len(&contents) != 0 ||
182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) ||
183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_len(&contents) != 0 ||
184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      value != 42) {
186e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData6, sizeof(kData6));
190e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // optional element.
191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      present ||
193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !present ||
195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_len(&contents) != 3 ||
19669939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
197e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData6, sizeof(kData6));
201e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // optional octet string.
202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      present ||
204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_len(&contents) != 0 ||
205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) ||
206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !present ||
207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_len(&contents) != 1 ||
208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBS_data(&contents)[0] != 1) {
209e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData7, sizeof(kData7));
213e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // invalid optional octet string.
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) {
215e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData8, sizeof(kData8));
219e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // optional octet string.
220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      value != 42 ||
222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) ||
223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      value != 1) {
224e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kData9, sizeof(kData9));
228e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // invalid optional integer.
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) {
230e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
233bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez  unsigned tag;
234bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez  CBS_init(&data, kData1, sizeof(kData1));
235bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez  if (!CBS_get_any_asn1(&data, &contents, &tag) ||
236bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez      tag != CBS_ASN1_SEQUENCE ||
237bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez      CBS_len(&contents) != 2 ||
23869939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
239bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez    return false;
240bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez  }
241bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez
242bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez  size_t header_len;
243bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez  CBS_init(&data, kData1, sizeof(kData1));
244bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez  if (!CBS_get_any_asn1_element(&data, &contents, &tag, &header_len) ||
245bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez      tag != CBS_ASN1_SEQUENCE ||
246bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez      header_len != 2 ||
247bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez      CBS_len(&contents) != 4 ||
24869939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(CBS_data(&contents), "\x30\x02\x01\x02", 2) != 0) {
249bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez    return false;
250bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez  }
251bb1ceac29bc7a18b94e3da78057dc41aa7071784Steven Valdez
252e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
255e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestGetOptionalASN1Bool() {
256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01};
259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
260e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CBS data;
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, NULL, 0);
262e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  int val = 2;
263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      val != 0) {
265e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kTrue, sizeof(kTrue));
269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  val = 2;
270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      val != 1) {
272e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kFalse, sizeof(kFalse));
276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  val = 2;
277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) ||
278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      val != 0) {
279e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&data, kInvalid, sizeof(kInvalid));
283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) {
284e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
287e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
290e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestCBBBasic() {
291c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc};
292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *buf;
293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t buf_len;
294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBB cbb;
295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBB_init(&cbb, 100)) {
297e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBB_cleanup(&cbb);
300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
301e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_init(&cbb, 0)) {
302e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
303e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
304e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_add_u8(&cbb, 1) ||
305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u16(&cbb, 0x203) ||
306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u24(&cbb, 0x40506) ||
307c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      !CBB_add_u32(&cbb, 0x708090a) ||
308c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      !CBB_add_bytes(&cbb, (const uint8_t*) "\x0b\x0c", 2) ||
309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_finish(&cbb, &buf, &buf_len)) {
310e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
311e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
314f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin  bssl::UniquePtr<uint8_t> scoper(buf);
31569939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan  return buf_len == sizeof(kExpected) &&
31669939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan         OPENSSL_memcmp(buf, kExpected, buf_len) == 0;
317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
319e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestCBBFixed() {
3201b249678059ecd918235790a7a0471771cc4e5ceDavid Benjamin  bssl::ScopedCBB cbb;
321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t buf[1];
322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *out_buf;
323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t out_size;
324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
325c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (!CBB_init_fixed(cbb.get(), NULL, 0) ||
326c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      !CBB_finish(cbb.get(), &out_buf, &out_size) ||
327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      out_buf != NULL ||
328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      out_size != 0) {
329e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
332c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  cbb.Reset();
333c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (!CBB_init_fixed(cbb.get(), buf, 1) ||
334c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      !CBB_add_u8(cbb.get(), 1) ||
335c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      !CBB_finish(cbb.get(), &out_buf, &out_size) ||
336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      out_buf != buf ||
337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      out_size != 1 ||
338d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      buf[0] != 1) {
339e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
342c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  cbb.Reset();
343c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (!CBB_init_fixed(cbb.get(), buf, 1) ||
344c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      !CBB_add_u8(cbb.get(), 1) ||
345c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      CBB_add_u8(cbb.get(), 2)) {
346c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
347c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
348c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
349e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
352e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestCBBFinishChild() {
353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBB cbb, child;
354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *out_buf;
355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t out_size;
356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
357e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_init(&cbb, 16)) {
358e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
359e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
360e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBB_finish(&child, &out_buf, &out_size) ||
362e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !CBB_finish(&cbb, &out_buf, &out_size)) {
363e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
364e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
366f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin  bssl::UniquePtr<uint8_t> scoper(out_buf);
367e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return out_size == 1 && out_buf[0] == 0;
368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
370e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestCBBPrefixed() {
371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3,
372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                                      4, 5, 6, 5, 4, 1, 0, 1, 2};
373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *buf;
374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t buf_len;
375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBB cbb, contents, inner_contents, inner_inner_contents;
376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3774139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (!CBB_init(&cbb, 0) ||
3784139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      CBB_len(&cbb) != 0 ||
3794139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !CBB_add_u8_length_prefixed(&cbb, &contents) ||
380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u8_length_prefixed(&cbb, &contents) ||
381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u8(&contents, 1) ||
3824139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      CBB_len(&contents) != 1 ||
3834139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !CBB_flush(&cbb) ||
3844139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      CBB_len(&cbb) != 3 ||
385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u16_length_prefixed(&cbb, &contents) ||
386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u16(&contents, 0x203) ||
387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u24_length_prefixed(&cbb, &contents) ||
388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u24(&contents, 0x40506) ||
389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u8_length_prefixed(&cbb, &contents) ||
390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u8_length_prefixed(&contents, &inner_contents) ||
391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u8(&inner_contents, 1) ||
392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) ||
393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u8(&inner_inner_contents, 2) ||
394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_finish(&cbb, &buf, &buf_len)) {
395e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
396e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
399f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin  bssl::UniquePtr<uint8_t> scoper(buf);
40069939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan  return buf_len == sizeof(kExpected) &&
40169939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan         OPENSSL_memcmp(buf, kExpected, buf_len) == 0;
402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
404e99801b603dea8893dcc61c70b327ef2d00b652cKenny Rootstatic bool TestCBBDiscardChild() {
4051b249678059ecd918235790a7a0471771cc4e5ceDavid Benjamin  bssl::ScopedCBB cbb;
406e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  CBB contents, inner_contents, inner_inner_contents;
407e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root
408e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  if (!CBB_init(cbb.get(), 0) ||
409e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u8(cbb.get(), 0xaa)) {
410e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root    return false;
411e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  }
412e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root
413e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  // Discarding |cbb|'s children preserves the byte written.
414e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  CBB_discard_child(cbb.get());
415e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root
416e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  if (!CBB_add_u8_length_prefixed(cbb.get(), &contents) ||
417e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u8_length_prefixed(cbb.get(), &contents) ||
418e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u8(&contents, 0xbb) ||
419e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u16_length_prefixed(cbb.get(), &contents) ||
420e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u16(&contents, 0xcccc) ||
421e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u24_length_prefixed(cbb.get(), &contents) ||
422e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u24(&contents, 0xdddddd) ||
423e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u8_length_prefixed(cbb.get(), &contents) ||
424e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u8(&contents, 0xff) ||
425e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u8_length_prefixed(&contents, &inner_contents) ||
426e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u8(&inner_contents, 0x42) ||
427e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) ||
428e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !CBB_add_u8(&inner_inner_contents, 0x99)) {
429e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root    return false;
430e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  }
431e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root
432e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  // Discard everything from |inner_contents| down.
433e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  CBB_discard_child(&contents);
434e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root
435e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  uint8_t *buf;
436e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  size_t buf_len;
437e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  if (!CBB_finish(cbb.get(), &buf, &buf_len)) {
438e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root    return false;
439e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  }
440f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin  bssl::UniquePtr<uint8_t> scoper(buf);
441e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root
442e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  static const uint8_t kExpected[] = {
443e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root        0xaa,
444e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root        0,
445e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root        1, 0xbb,
446e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root        0, 2, 0xcc, 0xcc,
447e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root        0, 0, 3, 0xdd, 0xdd, 0xdd,
448e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root        1, 0xff,
449e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  };
45069939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan  return buf_len == sizeof(kExpected) &&
45169939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan         OPENSSL_memcmp(buf, kExpected, buf_len) == 0;
452e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root}
453e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root
454e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestCBBMisuse() {
455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBB cbb, child, contents;
456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *buf;
457d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t buf_len;
458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
459e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_init(&cbb, 0)) {
460e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
461e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
462e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u8(&child, 1) ||
464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_u8(&cbb, 2)) {
465e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
466e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
469e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // Since we wrote to |cbb|, |child| is now invalid and attempts to write to
470e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // it should fail.
471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (CBB_add_u8(&child, 1) ||
472d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBB_add_u16(&child, 1) ||
473d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBB_add_u24(&child, 1) ||
474d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBB_add_u8_length_prefixed(&child, &contents) ||
475d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBB_add_u16_length_prefixed(&child, &contents) ||
476d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBB_add_asn1(&child, &contents, 1) ||
477d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBB_add_bytes(&child, (const uint8_t*) "a", 1)) {
478d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "CBB operation on invalid CBB did not fail.\n");
479e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
480e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
481d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
482d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
483e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_finish(&cbb, &buf, &buf_len)) {
484e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
485e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
486d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
487f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin  bssl::UniquePtr<uint8_t> scoper(buf);
488d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
489e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (buf_len != 3 ||
49069939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(buf, "\x01\x01\x02", 3) != 0) {
491e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
492e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
493e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
494d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
495d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
496e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestCBBASN1() {
497d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
498e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint8_t *buf;
499d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t buf_len;
500d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBB cbb, contents, inner_contents;
501d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
502e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_init(&cbb, 0)) {
503e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
504e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
505e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
506d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) ||
507d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_finish(&cbb, &buf, &buf_len)) {
508e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
509e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
510d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
511f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin  bssl::UniquePtr<uint8_t> scoper(buf);
512d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
51369939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan  if (buf_len != sizeof(kExpected) ||
51469939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(buf, kExpected, buf_len) != 0) {
515e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
516d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
517d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
518e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  std::vector<uint8_t> test_data(100000, 0x42);
519d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
520e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_init(&cbb, 0)) {
521e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
522e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
523e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
5244139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !CBB_add_bytes(&contents, test_data.data(), 130) ||
525d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_finish(&cbb, &buf, &buf_len)) {
526e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
527e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
528d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
529e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  scoper.reset(buf);
530d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
531d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (buf_len != 3 + 130 ||
53269939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(buf, "\x30\x81\x82", 3) != 0 ||
53369939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(buf + 3, test_data.data(), 130) != 0) {
534e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
535d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
536d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
537e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_init(&cbb, 0)) {
538e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
539e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
540e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
5414139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !CBB_add_bytes(&contents, test_data.data(), 1000) ||
542d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_finish(&cbb, &buf, &buf_len)) {
543e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
544e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
545d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
546e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  scoper.reset(buf);
547d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
548d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (buf_len != 4 + 1000 ||
54969939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
55069939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(buf + 4, test_data.data(), 1000)) {
551e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
552d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
553d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
554e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_init(&cbb, 0)) {
555e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
556e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
557e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
558d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_add_asn1(&contents, &inner_contents, 0x30) ||
5594139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !CBB_add_bytes(&inner_contents, test_data.data(), 100000) ||
560d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !CBB_finish(&cbb, &buf, &buf_len)) {
561e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CBB_cleanup(&cbb);
562e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
563d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
564e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  scoper.reset(buf);
565d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
566d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (buf_len != 5 + 5 + 100000 ||
56769939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) !=
56869939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan          0 ||
56969939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(buf + 10, test_data.data(), 100000)) {
570e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
571d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
572d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
573e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
574d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
575d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
576e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool DoBerConvert(const char *name,
577e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                         const uint8_t *der_expected, size_t der_len,
578e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                         const uint8_t *ber, size_t ber_len) {
579d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS in;
580d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *out;
581d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t out_len;
582d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
583d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CBS_init(&in, ber, ber_len);
584d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) {
585d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
586e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
587d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
588f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin  bssl::UniquePtr<uint8_t> scoper(out);
589d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
590d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (out == NULL) {
591d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (ber_len != der_len ||
59269939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan        OPENSSL_memcmp(der_expected, ber, ber_len) != 0) {
593d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      fprintf(stderr, "%s: incorrect unconverted result.\n", name);
594e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      return false;
595d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
596d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
597e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return true;
598d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
599d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
600d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (out_len != der_len ||
60169939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      OPENSSL_memcmp(out, der_expected, der_len) != 0) {
602d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "%s: incorrect converted result.\n", name);
603e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
604d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
605d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
606e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
607d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
608d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
609e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestBerConvert() {
610d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
611d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
612e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // kIndefBER contains a SEQUENCE with an indefinite length.
613d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
614d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
615d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  // kOctetStringBER contains an indefinite length OCTET STRING with two parts.
617e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // These parts need to be concatenated in DER form.
618d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0,    1,
619d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                                            0x04, 0x02, 2,    3,    0x00, 0x00};
620d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
621d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
622e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite
623e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // length elements extensively.
624d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kNSSBER[] = {
625d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
626d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x04,
627d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
628d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
629d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90,
630d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04,
631d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x10, 0x38, 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b,
632d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0xf0, 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
633d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  };
634d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
635d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const uint8_t kNSSDER[] = {
636d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86,
637d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04,
638d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06,
639d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84,
640d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8,
641d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38,
642d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0,
643d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
644d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  };
645d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6464969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  // kConstructedStringBER contains a deeply-nested constructed OCTET STRING.
6474969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  // The BER conversion collapses this to one level deep, but not completely.
6484969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  static const uint8_t kConstructedStringBER[] = {
6494969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      0xa0, 0x10, 0x24, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01,
6504969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      0x01, 0x24, 0x06, 0x04, 0x01, 0x02, 0x04, 0x01, 0x03,
6514969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  };
6524969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  static const uint8_t kConstructedStringDER[] = {
6534969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      0xa0, 0x08, 0x04, 0x02, 0x00, 0x01, 0x04, 0x02, 0x02, 0x03,
6544969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  };
6554969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
656e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
657e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                      kSimpleBER, sizeof(kSimpleBER)) &&
658e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
659e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                      sizeof(kIndefBER)) &&
660e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         DoBerConvert("kOctetStringBER", kOctetStringDER,
661e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                      sizeof(kOctetStringDER), kOctetStringBER,
662e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                      sizeof(kOctetStringBER)) &&
663e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
6644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                      sizeof(kNSSBER)) &&
6654969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin         DoBerConvert("kConstructedStringBER", kConstructedStringDER,
6664969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                      sizeof(kConstructedStringDER), kConstructedStringBER,
6674969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                      sizeof(kConstructedStringBER));
6684969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
6694969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
6704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjaminstruct ImplicitStringTest {
6714969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  const char *in;
6724969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  size_t in_len;
6734969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  bool ok;
6744969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  const char *out;
6754969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  size_t out_len;
6764969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin};
6774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
6784969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjaminstatic const ImplicitStringTest kImplicitStringTests[] = {
6794969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    // A properly-encoded string.
6804969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    {"\x80\x03\x61\x61\x61", 5, true, "aaa", 3},
6814969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    // An implicit-tagged string.
6824969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    {"\xa0\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, true, "aaa", 3},
6834969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    // |CBS_get_asn1_implicit_string| only accepts one level deep of nesting.
6844969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    {"\xa0\x0b\x24\x06\x04\x01\x61\x04\x01\x61\x04\x01\x61", 13, false, nullptr,
6854969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin     0},
6864969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    // The outer tag must match.
6874969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    {"\x81\x03\x61\x61\x61", 5, false, nullptr, 0},
6884969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    {"\xa1\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, false, nullptr, 0},
6894969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    // The inner tag must match.
6904969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    {"\xa1\x09\x0c\x01\x61\x0c\x01\x61\x0c\x01\x61", 11, false, nullptr, 0},
6914969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin};
6924969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
6934969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjaminstatic bool TestImplicitString() {
6944969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  for (const auto &test : kImplicitStringTests) {
6954969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    uint8_t *storage = nullptr;
6964969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    CBS in, out;
6974969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    CBS_init(&in, reinterpret_cast<const uint8_t *>(test.in), test.in_len);
6984969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    int ok = CBS_get_asn1_implicit_string(&in, &out, &storage,
6994969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                          CBS_ASN1_CONTEXT_SPECIFIC | 0,
7004969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                          CBS_ASN1_OCTETSTRING);
701f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin    bssl::UniquePtr<uint8_t> scoper(storage);
7024969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
7034969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (static_cast<bool>(ok) != test.ok) {
7044969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      fprintf(stderr, "CBS_get_asn1_implicit_string unexpectedly %s\n",
7054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin              ok ? "succeeded" : "failed");
7064969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      return false;
7074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
7084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
7094969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (ok && (CBS_len(&out) != test.out_len ||
71069939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan               OPENSSL_memcmp(CBS_data(&out), test.out, test.out_len) != 0)) {
7114969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      fprintf(stderr, "CBS_get_asn1_implicit_string gave the wrong output\n");
7124969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      return false;
7134969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
7144969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  }
7154969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
7164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  return true;
717d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
718d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
719e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystruct ASN1Uint64Test {
720d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint64_t value;
721d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const char *encoding;
722d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t encoding_len;
723d9e397b599b13d642138480a28c14db7a136bf0Adam Langley};
724d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
725e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ASN1Uint64Test kASN1Uint64Tests[] = {
726e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {0, "\x02\x01\x00", 3},
727e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {1, "\x02\x01\x01", 3},
728e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {127, "\x02\x01\x7f", 3},
729e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {128, "\x02\x02\x00\x80", 4},
730e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
7314139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    {UINT64_C(0x0102030405060708),
732e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley     "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
7334139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    {UINT64_C(0xffffffffffffffff),
734e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
735e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley};
736e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
737e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystruct ASN1InvalidUint64Test {
738d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const char *encoding;
739d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t encoding_len;
740d9e397b599b13d642138480a28c14db7a136bf0Adam Langley};
741d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
742e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ASN1InvalidUint64Test kASN1InvalidUint64Tests[] = {
743e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    // Bad tag.
744e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {"\x03\x01\x00", 3},
745e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    // Empty contents.
746e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {"\x02\x00", 2},
747e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    // Negative number.
748e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {"\x02\x01\x80", 3},
749e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    // Overflow.
750e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
751e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    // Leading zeros.
752e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    {"\x02\x02\x00\x01", 4},
753e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley};
754d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
755e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestASN1Uint64() {
756f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Uint64Tests); i++) {
757e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    const ASN1Uint64Test *test = &kASN1Uint64Tests[i];
758d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS cbs;
759d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    uint64_t value;
760d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBB cbb;
761d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    uint8_t *out;
762d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    size_t len;
763d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
764d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
765d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!CBS_get_asn1_uint64(&cbs, &value) ||
766d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        CBS_len(&cbs) != 0 ||
767d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        value != test->value) {
768e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      return false;
769d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
770d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
771d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!CBB_init(&cbb, 0)) {
772e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      return false;
773d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
774d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!CBB_add_asn1_uint64(&cbb, test->value) ||
775d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        !CBB_finish(&cbb, &out, &len)) {
776d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      CBB_cleanup(&cbb);
777e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      return false;
778d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
779f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin    bssl::UniquePtr<uint8_t> scoper(out);
78069939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan    if (len != test->encoding_len ||
78169939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan        OPENSSL_memcmp(out, test->encoding, len) != 0) {
782e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      return false;
783d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
784d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
785d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
786f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kASN1InvalidUint64Tests); i++) {
787e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    const ASN1InvalidUint64Test *test = &kASN1InvalidUint64Tests[i];
788d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS cbs;
789d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    uint64_t value;
790d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
791d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
792d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (CBS_get_asn1_uint64(&cbs, &value)) {
793e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      return false;
794d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
795d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
796d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
797e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
798d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
799d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
8004139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleystatic bool TestZero() {
801b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBB cbb;
802b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBB_zero(&cbb);
803b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  // Calling |CBB_cleanup| on a zero-state |CBB| must not crash.
804b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBB_cleanup(&cbb);
8054139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  return true;
8064139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley}
8074139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
8084139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleystatic bool TestCBBReserve() {
8094139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  uint8_t buf[10];
8104139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  uint8_t *ptr;
8114139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  size_t len;
8121b249678059ecd918235790a7a0471771cc4e5ceDavid Benjamin  bssl::ScopedCBB cbb;
8134139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) ||
8144139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      // Too large.
815c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      CBB_reserve(cbb.get(), &ptr, 11)) {
816c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
817c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
818c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
819c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  cbb.Reset();
820c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) ||
8214139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      // Successfully reserve the entire space.
8224139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !CBB_reserve(cbb.get(), &ptr, 10) ||
8234139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ptr != buf ||
8244139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      // Advancing under the maximum bytes is legal.
8254139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !CBB_did_write(cbb.get(), 5) ||
8264139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !CBB_finish(cbb.get(), NULL, &len) ||
8274139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      len != 5) {
8284139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    return false;
8294139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  }
8304139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  return true;
831b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root}
832b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
833c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminstatic bool TestStickyError() {
834c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  // Write an input that exceeds the limit for its length prefix.
8351b249678059ecd918235790a7a0471771cc4e5ceDavid Benjamin  bssl::ScopedCBB cbb;
836c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  CBB child;
837c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  static const uint8_t kZeros[256] = {0};
838c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (!CBB_init(cbb.get(), 0) ||
839c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      !CBB_add_u8_length_prefixed(cbb.get(), &child) ||
840c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      !CBB_add_bytes(&child, kZeros, sizeof(kZeros))) {
841c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
842c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
843c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
844c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (CBB_flush(cbb.get())) {
845c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    fprintf(stderr, "CBB_flush unexpectedly succeeded.\n");
846c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
847c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
848c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
849c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  // All future operations should fail.
850c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  uint8_t *ptr;
851c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  size_t len;
852c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (CBB_add_u8(cbb.get(), 0) ||
853c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      CBB_finish(cbb.get(), &ptr, &len)) {
854c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    fprintf(stderr, "Future operations unexpectedly succeeded.\n");
855c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
856c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
857c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
858c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  // Write an input that cannot fit in a fixed CBB.
859c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  cbb.Reset();
860c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  uint8_t buf;
861c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (!CBB_init_fixed(cbb.get(), &buf, 1)) {
862c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
863c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
864c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
865c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (CBB_add_bytes(cbb.get(), kZeros, sizeof(kZeros))) {
866c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    fprintf(stderr, "CBB_add_bytes unexpectedly succeeded.\n");
867c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
868c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
869c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
870c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  // All future operations should fail.
871c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (CBB_add_u8(cbb.get(), 0) ||
872c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      CBB_finish(cbb.get(), &ptr, &len)) {
873c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    fprintf(stderr, "Future operations unexpectedly succeeded.\n");
874c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
875c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
876c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
877c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  // Write a u32 that cannot fit in a u24.
878c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  cbb.Reset();
879c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (!CBB_init(cbb.get(), 0)) {
880c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
881c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
882c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
883c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (CBB_add_u24(cbb.get(), 1u << 24)) {
884c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    fprintf(stderr, "CBB_add_u24 unexpectedly succeeded.\n");
885c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
886c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
887c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
888c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  // All future operations should fail.
889c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (CBB_add_u8(cbb.get(), 0) ||
890c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      CBB_finish(cbb.get(), &ptr, &len)) {
891c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    fprintf(stderr, "Future operations unexpectedly succeeded.\n");
892c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return false;
893c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
894c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
895c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  return true;
896c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin}
897c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
898e7531f038363d24a103c820cff38898455ff66feSteven Valdezstatic bool TestBitString() {
899e7531f038363d24a103c820cff38898455ff66feSteven Valdez  static const std::vector<uint8_t> kValidBitStrings[] = {
900e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {0x00},                                      // 0 bits
901e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {0x07, 0x80},                                // 1 bit
902e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {0x04, 0xf0},                                // 4 bits
903e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {0x00, 0xff},                                // 8 bits
904e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0},  // 42 bits
905e7531f038363d24a103c820cff38898455ff66feSteven Valdez  };
906e7531f038363d24a103c820cff38898455ff66feSteven Valdez  for (const auto& test : kValidBitStrings) {
907e7531f038363d24a103c820cff38898455ff66feSteven Valdez    CBS cbs;
908e7531f038363d24a103c820cff38898455ff66feSteven Valdez    CBS_init(&cbs, test.data(), test.size());
909e7531f038363d24a103c820cff38898455ff66feSteven Valdez    if (!CBS_is_valid_asn1_bitstring(&cbs)) {
910e7531f038363d24a103c820cff38898455ff66feSteven Valdez      return false;
911e7531f038363d24a103c820cff38898455ff66feSteven Valdez    }
912e7531f038363d24a103c820cff38898455ff66feSteven Valdez  }
913e7531f038363d24a103c820cff38898455ff66feSteven Valdez
914e7531f038363d24a103c820cff38898455ff66feSteven Valdez  static const std::vector<uint8_t> kInvalidBitStrings[] = {
915e7531f038363d24a103c820cff38898455ff66feSteven Valdez      // BIT STRINGs always have a leading byte.
91669939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan      std::vector<uint8_t>{},
917e7531f038363d24a103c820cff38898455ff66feSteven Valdez      // It's not possible to take an unused bit off the empty string.
918e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {0x01},
919e7531f038363d24a103c820cff38898455ff66feSteven Valdez      // There can be at most 7 unused bits.
920e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {0x08, 0xff},
921e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {0xff, 0xff},
922e7531f038363d24a103c820cff38898455ff66feSteven Valdez      // All unused bits must be cleared.
923e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {0x06, 0xff, 0xc1},
924e7531f038363d24a103c820cff38898455ff66feSteven Valdez  };
925e7531f038363d24a103c820cff38898455ff66feSteven Valdez  for (const auto& test : kInvalidBitStrings) {
926e7531f038363d24a103c820cff38898455ff66feSteven Valdez    CBS cbs;
927e7531f038363d24a103c820cff38898455ff66feSteven Valdez    CBS_init(&cbs, test.data(), test.size());
928e7531f038363d24a103c820cff38898455ff66feSteven Valdez    if (CBS_is_valid_asn1_bitstring(&cbs)) {
929e7531f038363d24a103c820cff38898455ff66feSteven Valdez      return false;
930e7531f038363d24a103c820cff38898455ff66feSteven Valdez    }
931e7531f038363d24a103c820cff38898455ff66feSteven Valdez
932e7531f038363d24a103c820cff38898455ff66feSteven Valdez    // CBS_asn1_bitstring_has_bit returns false on invalid inputs.
933e7531f038363d24a103c820cff38898455ff66feSteven Valdez    if (CBS_asn1_bitstring_has_bit(&cbs, 0)) {
934e7531f038363d24a103c820cff38898455ff66feSteven Valdez      return false;
935e7531f038363d24a103c820cff38898455ff66feSteven Valdez    }
936e7531f038363d24a103c820cff38898455ff66feSteven Valdez  }
937e7531f038363d24a103c820cff38898455ff66feSteven Valdez
938e7531f038363d24a103c820cff38898455ff66feSteven Valdez  static const struct {
939e7531f038363d24a103c820cff38898455ff66feSteven Valdez    std::vector<uint8_t> in;
940e7531f038363d24a103c820cff38898455ff66feSteven Valdez    unsigned bit;
941e7531f038363d24a103c820cff38898455ff66feSteven Valdez    bool bit_set;
942e7531f038363d24a103c820cff38898455ff66feSteven Valdez  } kBitTests[] = {
943e7531f038363d24a103c820cff38898455ff66feSteven Valdez      // Basic tests.
944e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x00}, 0, false},
945e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x07, 0x80}, 0, true},
946e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 0, false},
947e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 1, false},
948e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 2, false},
949e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 3, false},
950e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 4, true},
951e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 5, true},
952e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 6, true},
953e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 7, true},
954e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 8, false},
955e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 9, true},
956e7531f038363d24a103c820cff38898455ff66feSteven Valdez      // Out-of-bounds bits return 0.
957e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 10, false},
958e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 15, false},
959e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 16, false},
960e7531f038363d24a103c820cff38898455ff66feSteven Valdez      {{0x06, 0x0f, 0x40}, 1000, false},
961e7531f038363d24a103c820cff38898455ff66feSteven Valdez  };
962e7531f038363d24a103c820cff38898455ff66feSteven Valdez  for (const auto& test : kBitTests) {
963e7531f038363d24a103c820cff38898455ff66feSteven Valdez    CBS cbs;
964e7531f038363d24a103c820cff38898455ff66feSteven Valdez    CBS_init(&cbs, test.in.data(), test.in.size());
965e7531f038363d24a103c820cff38898455ff66feSteven Valdez    if (CBS_asn1_bitstring_has_bit(&cbs, test.bit) !=
966e7531f038363d24a103c820cff38898455ff66feSteven Valdez        static_cast<int>(test.bit_set)) {
967e7531f038363d24a103c820cff38898455ff66feSteven Valdez      return false;
968e7531f038363d24a103c820cff38898455ff66feSteven Valdez    }
969e7531f038363d24a103c820cff38898455ff66feSteven Valdez  }
970e7531f038363d24a103c820cff38898455ff66feSteven Valdez
971e7531f038363d24a103c820cff38898455ff66feSteven Valdez  return true;
972e7531f038363d24a103c820cff38898455ff66feSteven Valdez}
973e7531f038363d24a103c820cff38898455ff66feSteven Valdez
9741b249678059ecd918235790a7a0471771cc4e5ceDavid Benjaminint main() {
975d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  CRYPTO_library_init();
976d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
977e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!TestSkip() ||
978e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestGetUint() ||
979e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestGetPrefixed() ||
980e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestGetPrefixedBad() ||
981e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestGetASN1() ||
982e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestCBBBasic() ||
983e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestCBBFixed() ||
984e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestCBBFinishChild() ||
985e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestCBBMisuse() ||
986e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestCBBPrefixed() ||
987e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      !TestCBBDiscardChild() ||
988e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestCBBASN1() ||
989e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestBerConvert() ||
9904969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      !TestImplicitString() ||
991e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !TestASN1Uint64() ||
992b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      !TestGetOptionalASN1Bool() ||
9934139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !TestZero() ||
994c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      !TestCBBReserve() ||
995e7531f038363d24a103c820cff38898455ff66feSteven Valdez      !TestStickyError() ||
996e7531f038363d24a103c820cff38898455ff66feSteven Valdez      !TestBitString()) {
997d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 1;
998d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
999d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1000d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  printf("PASS\n");
1001d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 0;
1002d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
1003