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 #include <string.h>
18
19 #include <vector>
20
21 #include <openssl/crypto.h>
22 #include <openssl/bytestring.h>
23
24 #include "internal.h"
25 #include "../internal.h"
26 #include "../test/scoped_types.h"
27
28
TestSkip()29 static bool TestSkip() {
30 static const uint8_t kData[] = {1, 2, 3};
31 CBS data;
32
33 CBS_init(&data, kData, sizeof(kData));
34 return CBS_len(&data) == 3 &&
35 CBS_skip(&data, 1) &&
36 CBS_len(&data) == 2 &&
37 CBS_skip(&data, 2) &&
38 CBS_len(&data) == 0 &&
39 !CBS_skip(&data, 1);
40 }
41
TestGetUint()42 static bool TestGetUint() {
43 static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
44 uint8_t u8;
45 uint16_t u16;
46 uint32_t u32;
47 CBS data;
48
49 CBS_init(&data, kData, sizeof(kData));
50 return CBS_get_u8(&data, &u8) &&
51 u8 == 1 &&
52 CBS_get_u16(&data, &u16) &&
53 u16 == 0x203 &&
54 CBS_get_u24(&data, &u32) &&
55 u32 == 0x40506 &&
56 CBS_get_u32(&data, &u32) &&
57 u32 == 0x708090a &&
58 !CBS_get_u8(&data, &u8);
59 }
60
TestGetPrefixed()61 static bool TestGetPrefixed() {
62 static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1};
63 uint8_t u8;
64 uint16_t u16;
65 uint32_t u32;
66 CBS data, prefixed;
67
68 CBS_init(&data, kData, sizeof(kData));
69 return CBS_get_u8_length_prefixed(&data, &prefixed) &&
70 CBS_len(&prefixed) == 1 &&
71 CBS_get_u8(&prefixed, &u8) &&
72 u8 == 2 &&
73 CBS_get_u16_length_prefixed(&data, &prefixed) &&
74 CBS_len(&prefixed) == 2 &&
75 CBS_get_u16(&prefixed, &u16) &&
76 u16 == 0x304 &&
77 CBS_get_u24_length_prefixed(&data, &prefixed) &&
78 CBS_len(&prefixed) == 3 &&
79 CBS_get_u24(&prefixed, &u32) &&
80 u32 == 0x30201;
81 }
82
TestGetPrefixedBad()83 static bool TestGetPrefixedBad() {
84 static const uint8_t kData1[] = {2, 1};
85 static const uint8_t kData2[] = {0, 2, 1};
86 static const uint8_t kData3[] = {0, 0, 2, 1};
87 CBS data, prefixed;
88
89 CBS_init(&data, kData1, sizeof(kData1));
90 if (CBS_get_u8_length_prefixed(&data, &prefixed)) {
91 return false;
92 }
93
94 CBS_init(&data, kData2, sizeof(kData2));
95 if (CBS_get_u16_length_prefixed(&data, &prefixed)) {
96 return false;
97 }
98
99 CBS_init(&data, kData3, sizeof(kData3));
100 if (CBS_get_u24_length_prefixed(&data, &prefixed)) {
101 return false;
102 }
103
104 return true;
105 }
106
TestGetASN1()107 static bool TestGetASN1() {
108 static const uint8_t kData1[] = {0x30, 2, 1, 2};
109 static const uint8_t kData2[] = {0x30, 3, 1, 2};
110 static const uint8_t kData3[] = {0x30, 0x80};
111 static const uint8_t kData4[] = {0x30, 0x81, 1, 1};
112 static const uint8_t kData5[] = {0x30, 0x82, 0, 1, 1};
113 static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1};
114 static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1};
115 static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1};
116 static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff};
117
118 CBS data, contents;
119 int present;
120 uint64_t value;
121
122 CBS_init(&data, kData1, sizeof(kData1));
123 if (CBS_peek_asn1_tag(&data, 0x1) ||
124 !CBS_peek_asn1_tag(&data, 0x30)) {
125 return false;
126 }
127 if (!CBS_get_asn1(&data, &contents, 0x30) ||
128 CBS_len(&contents) != 2 ||
129 memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
130 return false;
131 }
132
133 CBS_init(&data, kData2, sizeof(kData2));
134 // data is truncated
135 if (CBS_get_asn1(&data, &contents, 0x30)) {
136 return false;
137 }
138
139 CBS_init(&data, kData3, sizeof(kData3));
140 // zero byte length of length
141 if (CBS_get_asn1(&data, &contents, 0x30)) {
142 return false;
143 }
144
145 CBS_init(&data, kData4, sizeof(kData4));
146 // long form mistakenly used.
147 if (CBS_get_asn1(&data, &contents, 0x30)) {
148 return false;
149 }
150
151 CBS_init(&data, kData5, sizeof(kData5));
152 // length takes too many bytes.
153 if (CBS_get_asn1(&data, &contents, 0x30)) {
154 return false;
155 }
156
157 CBS_init(&data, kData1, sizeof(kData1));
158 // wrong tag.
159 if (CBS_get_asn1(&data, &contents, 0x31)) {
160 return false;
161 }
162
163 CBS_init(&data, NULL, 0);
164 // peek at empty data.
165 if (CBS_peek_asn1_tag(&data, 0x30)) {
166 return false;
167 }
168
169 CBS_init(&data, NULL, 0);
170 // optional elements at empty data.
171 if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
172 present ||
173 !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
174 present ||
175 CBS_len(&contents) != 0 ||
176 !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) ||
177 CBS_len(&contents) != 0 ||
178 !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
179 value != 42) {
180 return false;
181 }
182
183 CBS_init(&data, kData6, sizeof(kData6));
184 // optional element.
185 if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
186 present ||
187 !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
188 !present ||
189 CBS_len(&contents) != 3 ||
190 memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
191 return false;
192 }
193
194 CBS_init(&data, kData6, sizeof(kData6));
195 // optional octet string.
196 if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
197 present ||
198 CBS_len(&contents) != 0 ||
199 !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) ||
200 !present ||
201 CBS_len(&contents) != 1 ||
202 CBS_data(&contents)[0] != 1) {
203 return false;
204 }
205
206 CBS_init(&data, kData7, sizeof(kData7));
207 // invalid optional octet string.
208 if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) {
209 return false;
210 }
211
212 CBS_init(&data, kData8, sizeof(kData8));
213 // optional octet string.
214 if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
215 value != 42 ||
216 !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) ||
217 value != 1) {
218 return false;
219 }
220
221 CBS_init(&data, kData9, sizeof(kData9));
222 // invalid optional integer.
223 if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) {
224 return false;
225 }
226
227 return true;
228 }
229
TestGetOptionalASN1Bool()230 static bool TestGetOptionalASN1Bool() {
231 static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
232 static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
233 static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01};
234
235 CBS data;
236 CBS_init(&data, NULL, 0);
237 int val = 2;
238 if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
239 val != 0) {
240 return false;
241 }
242
243 CBS_init(&data, kTrue, sizeof(kTrue));
244 val = 2;
245 if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
246 val != 1) {
247 return false;
248 }
249
250 CBS_init(&data, kFalse, sizeof(kFalse));
251 val = 2;
252 if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) ||
253 val != 0) {
254 return false;
255 }
256
257 CBS_init(&data, kInvalid, sizeof(kInvalid));
258 if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) {
259 return false;
260 }
261
262 return true;
263 }
264
TestCBBBasic()265 static bool TestCBBBasic() {
266 static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8};
267 uint8_t *buf;
268 size_t buf_len;
269 CBB cbb;
270
271 if (!CBB_init(&cbb, 100)) {
272 return false;
273 }
274 CBB_cleanup(&cbb);
275
276 if (!CBB_init(&cbb, 0)) {
277 return false;
278 }
279 if (!CBB_add_u8(&cbb, 1) ||
280 !CBB_add_u16(&cbb, 0x203) ||
281 !CBB_add_u24(&cbb, 0x40506) ||
282 !CBB_add_bytes(&cbb, (const uint8_t*) "\x07\x08", 2) ||
283 !CBB_finish(&cbb, &buf, &buf_len)) {
284 CBB_cleanup(&cbb);
285 return false;
286 }
287
288 ScopedOpenSSLBytes scoper(buf);
289 return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
290 }
291
TestCBBFixed()292 static bool TestCBBFixed() {
293 CBB cbb;
294 uint8_t buf[1];
295 uint8_t *out_buf;
296 size_t out_size;
297
298 if (!CBB_init_fixed(&cbb, NULL, 0) ||
299 CBB_add_u8(&cbb, 1) ||
300 !CBB_finish(&cbb, &out_buf, &out_size) ||
301 out_buf != NULL ||
302 out_size != 0) {
303 return false;
304 }
305
306 if (!CBB_init_fixed(&cbb, buf, 1) ||
307 !CBB_add_u8(&cbb, 1) ||
308 CBB_add_u8(&cbb, 2) ||
309 !CBB_finish(&cbb, &out_buf, &out_size) ||
310 out_buf != buf ||
311 out_size != 1 ||
312 buf[0] != 1) {
313 return false;
314 }
315
316 return true;
317 }
318
TestCBBFinishChild()319 static bool TestCBBFinishChild() {
320 CBB cbb, child;
321 uint8_t *out_buf;
322 size_t out_size;
323
324 if (!CBB_init(&cbb, 16)) {
325 return false;
326 }
327 if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
328 CBB_finish(&child, &out_buf, &out_size) ||
329 !CBB_finish(&cbb, &out_buf, &out_size)) {
330 CBB_cleanup(&cbb);
331 return false;
332 }
333 ScopedOpenSSLBytes scoper(out_buf);
334 return out_size == 1 && out_buf[0] == 0;
335 }
336
TestCBBPrefixed()337 static bool TestCBBPrefixed() {
338 static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3,
339 4, 5, 6, 5, 4, 1, 0, 1, 2};
340 uint8_t *buf;
341 size_t buf_len;
342 CBB cbb, contents, inner_contents, inner_inner_contents;
343
344 if (!CBB_init(&cbb, 0)) {
345 return false;
346 }
347 if (!CBB_add_u8_length_prefixed(&cbb, &contents) ||
348 !CBB_add_u8_length_prefixed(&cbb, &contents) ||
349 !CBB_add_u8(&contents, 1) ||
350 !CBB_add_u16_length_prefixed(&cbb, &contents) ||
351 !CBB_add_u16(&contents, 0x203) ||
352 !CBB_add_u24_length_prefixed(&cbb, &contents) ||
353 !CBB_add_u24(&contents, 0x40506) ||
354 !CBB_add_u8_length_prefixed(&cbb, &contents) ||
355 !CBB_add_u8_length_prefixed(&contents, &inner_contents) ||
356 !CBB_add_u8(&inner_contents, 1) ||
357 !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) ||
358 !CBB_add_u8(&inner_inner_contents, 2) ||
359 !CBB_finish(&cbb, &buf, &buf_len)) {
360 CBB_cleanup(&cbb);
361 return false;
362 }
363
364 ScopedOpenSSLBytes scoper(buf);
365 return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
366 }
367
TestCBBMisuse()368 static bool TestCBBMisuse() {
369 CBB cbb, child, contents;
370 uint8_t *buf;
371 size_t buf_len;
372
373 if (!CBB_init(&cbb, 0)) {
374 return false;
375 }
376 if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
377 !CBB_add_u8(&child, 1) ||
378 !CBB_add_u8(&cbb, 2)) {
379 CBB_cleanup(&cbb);
380 return false;
381 }
382
383 // Since we wrote to |cbb|, |child| is now invalid and attempts to write to
384 // it should fail.
385 if (CBB_add_u8(&child, 1) ||
386 CBB_add_u16(&child, 1) ||
387 CBB_add_u24(&child, 1) ||
388 CBB_add_u8_length_prefixed(&child, &contents) ||
389 CBB_add_u16_length_prefixed(&child, &contents) ||
390 CBB_add_asn1(&child, &contents, 1) ||
391 CBB_add_bytes(&child, (const uint8_t*) "a", 1)) {
392 fprintf(stderr, "CBB operation on invalid CBB did not fail.\n");
393 CBB_cleanup(&cbb);
394 return false;
395 }
396
397 if (!CBB_finish(&cbb, &buf, &buf_len)) {
398 CBB_cleanup(&cbb);
399 return false;
400 }
401 ScopedOpenSSLBytes scoper(buf);
402
403 if (buf_len != 3 ||
404 memcmp(buf, "\x01\x01\x02", 3) != 0) {
405 return false;
406 }
407 return true;
408 }
409
TestCBBASN1()410 static bool TestCBBASN1() {
411 static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
412 uint8_t *buf;
413 size_t buf_len;
414 CBB cbb, contents, inner_contents;
415
416 if (!CBB_init(&cbb, 0)) {
417 return false;
418 }
419 if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
420 !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) ||
421 !CBB_finish(&cbb, &buf, &buf_len)) {
422 CBB_cleanup(&cbb);
423 return false;
424 }
425 ScopedOpenSSLBytes scoper(buf);
426
427 if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) {
428 return false;
429 }
430
431 std::vector<uint8_t> test_data(100000, 0x42);
432
433 if (!CBB_init(&cbb, 0)) {
434 return false;
435 }
436 if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
437 !CBB_add_bytes(&contents, bssl::vector_data(&test_data), 130) ||
438 !CBB_finish(&cbb, &buf, &buf_len)) {
439 CBB_cleanup(&cbb);
440 return false;
441 }
442 scoper.reset(buf);
443
444 if (buf_len != 3 + 130 ||
445 memcmp(buf, "\x30\x81\x82", 3) != 0 ||
446 memcmp(buf + 3, bssl::vector_data(&test_data), 130) != 0) {
447 return false;
448 }
449
450 if (!CBB_init(&cbb, 0)) {
451 return false;
452 }
453 if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
454 !CBB_add_bytes(&contents, bssl::vector_data(&test_data), 1000) ||
455 !CBB_finish(&cbb, &buf, &buf_len)) {
456 CBB_cleanup(&cbb);
457 return false;
458 }
459 scoper.reset(buf);
460
461 if (buf_len != 4 + 1000 ||
462 memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
463 memcmp(buf + 4, bssl::vector_data(&test_data), 1000)) {
464 return false;
465 }
466
467 if (!CBB_init(&cbb, 0)) {
468 return false;
469 }
470 if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
471 !CBB_add_asn1(&contents, &inner_contents, 0x30) ||
472 !CBB_add_bytes(&inner_contents, bssl::vector_data(&test_data), 100000) ||
473 !CBB_finish(&cbb, &buf, &buf_len)) {
474 CBB_cleanup(&cbb);
475 return false;
476 }
477 scoper.reset(buf);
478
479 if (buf_len != 5 + 5 + 100000 ||
480 memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 ||
481 memcmp(buf + 10, bssl::vector_data(&test_data), 100000)) {
482 return false;
483 }
484
485 return true;
486 }
487
DoBerConvert(const char * name,const uint8_t * der_expected,size_t der_len,const uint8_t * ber,size_t ber_len)488 static bool DoBerConvert(const char *name,
489 const uint8_t *der_expected, size_t der_len,
490 const uint8_t *ber, size_t ber_len) {
491 CBS in;
492 uint8_t *out;
493 size_t out_len;
494
495 CBS_init(&in, ber, ber_len);
496 if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) {
497 fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
498 return false;
499 }
500 ScopedOpenSSLBytes scoper(out);
501
502 if (out == NULL) {
503 if (ber_len != der_len ||
504 memcmp(der_expected, ber, ber_len) != 0) {
505 fprintf(stderr, "%s: incorrect unconverted result.\n", name);
506 return false;
507 }
508
509 return true;
510 }
511
512 if (out_len != der_len ||
513 memcmp(out, der_expected, der_len) != 0) {
514 fprintf(stderr, "%s: incorrect converted result.\n", name);
515 return false;
516 }
517
518 return true;
519 }
520
TestBerConvert()521 static bool TestBerConvert() {
522 static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
523
524 // kIndefBER contains a SEQUENCE with an indefinite length.
525 static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
526 static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
527
528 // kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
529 // These parts need to be concatenated in DER form.
530 static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
531 0x04, 0x02, 2, 3, 0x00, 0x00};
532 static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
533
534 // kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite
535 // length elements extensively.
536 static const uint8_t kNSSBER[] = {
537 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
538 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x04,
539 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
540 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
541 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90,
542 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04,
543 0x10, 0x38, 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b,
544 0xf0, 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
545 };
546
547 static const uint8_t kNSSDER[] = {
548 0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86,
549 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04,
550 0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06,
551 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84,
552 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8,
553 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38,
554 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0,
555 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
556 };
557
558 return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
559 kSimpleBER, sizeof(kSimpleBER)) &&
560 DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
561 sizeof(kIndefBER)) &&
562 DoBerConvert("kOctetStringBER", kOctetStringDER,
563 sizeof(kOctetStringDER), kOctetStringBER,
564 sizeof(kOctetStringBER)) &&
565 DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
566 sizeof(kNSSBER));
567 }
568
569 struct ASN1Uint64Test {
570 uint64_t value;
571 const char *encoding;
572 size_t encoding_len;
573 };
574
575 static const ASN1Uint64Test kASN1Uint64Tests[] = {
576 {0, "\x02\x01\x00", 3},
577 {1, "\x02\x01\x01", 3},
578 {127, "\x02\x01\x7f", 3},
579 {128, "\x02\x02\x00\x80", 4},
580 {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
581 {OPENSSL_U64(0x0102030405060708),
582 "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
583 {OPENSSL_U64(0xffffffffffffffff),
584 "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
585 };
586
587 struct ASN1InvalidUint64Test {
588 const char *encoding;
589 size_t encoding_len;
590 };
591
592 static const ASN1InvalidUint64Test kASN1InvalidUint64Tests[] = {
593 // Bad tag.
594 {"\x03\x01\x00", 3},
595 // Empty contents.
596 {"\x02\x00", 2},
597 // Negative number.
598 {"\x02\x01\x80", 3},
599 // Overflow.
600 {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
601 // Leading zeros.
602 {"\x02\x02\x00\x01", 4},
603 };
604
TestASN1Uint64()605 static bool TestASN1Uint64() {
606 for (size_t i = 0; i < sizeof(kASN1Uint64Tests) / sizeof(kASN1Uint64Tests[0]);
607 i++) {
608 const ASN1Uint64Test *test = &kASN1Uint64Tests[i];
609 CBS cbs;
610 uint64_t value;
611 CBB cbb;
612 uint8_t *out;
613 size_t len;
614
615 CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
616 if (!CBS_get_asn1_uint64(&cbs, &value) ||
617 CBS_len(&cbs) != 0 ||
618 value != test->value) {
619 return false;
620 }
621
622 if (!CBB_init(&cbb, 0)) {
623 return false;
624 }
625 if (!CBB_add_asn1_uint64(&cbb, test->value) ||
626 !CBB_finish(&cbb, &out, &len)) {
627 CBB_cleanup(&cbb);
628 return false;
629 }
630 ScopedOpenSSLBytes scoper(out);
631 if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
632 return false;
633 }
634 }
635
636 for (size_t i = 0;
637 i < sizeof(kASN1InvalidUint64Tests) / sizeof(kASN1InvalidUint64Tests[0]);
638 i++) {
639 const ASN1InvalidUint64Test *test = &kASN1InvalidUint64Tests[i];
640 CBS cbs;
641 uint64_t value;
642
643 CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
644 if (CBS_get_asn1_uint64(&cbs, &value)) {
645 return false;
646 }
647 }
648
649 return true;
650 }
651
main(void)652 int main(void) {
653 CRYPTO_library_init();
654
655 if (!TestSkip() ||
656 !TestGetUint() ||
657 !TestGetPrefixed() ||
658 !TestGetPrefixedBad() ||
659 !TestGetASN1() ||
660 !TestCBBBasic() ||
661 !TestCBBFixed() ||
662 !TestCBBFinishChild() ||
663 !TestCBBMisuse() ||
664 !TestCBBPrefixed() ||
665 !TestCBBASN1() ||
666 !TestBerConvert() ||
667 !TestASN1Uint64() ||
668 !TestGetOptionalASN1Bool()) {
669 return 1;
670 }
671
672 printf("PASS\n");
673 return 0;
674 }
675