xref: /freebsd/contrib/bsnmp/tests/asn1.cc (revision ec0ea6efa1ad229d75c394c1a9b9cac33af2b1d3)
1 /*
2  * Copyright (c) 2020
3  *	Hartmut Brandt <harti@freebsd.org>
4  *	All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * :se ts=4
28  */
29 
30 #include "constbuf.h"
31 
32 extern "C" {
33 #include "asn1.h"
34 }
35 
36 #include "catch.hpp"
37 
38 #include <algorithm>
39 #include <cstdarg>
40 #include <cstdint>
41 #include <iostream>
42 #include <string>
43 #include <type_traits>
44 
45 using namespace test::literals;
46 
47 template<typename T>
48 static std::enable_if_t<!std::is_integral_v<T>, asn_buf>
49 mk_asn_buf(const T &b)
50 {
51 	asn_buf abuf;
52 
53 	abuf.asn_cptr = b.data();
54 	abuf.asn_len = b.size();
55 
56 	return abuf;
57 }
58 
59 static asn_buf
60 mk_asn_buf(asn_len_t len)
61 {
62 	asn_buf abuf;
63 
64 	abuf.asn_ptr = new u_char[len];
65 	abuf.asn_len = len;
66 
67 	return abuf;
68 }
69 
70 static std::string g_errstr;
71 
72 static void
73 save_g_errstr(const struct asn_buf *b, const char *fmt, ...)
74 {
75 	va_list ap;
76 
77 	char sbuf[20000];
78 	va_start(ap, fmt);
79 	vsprintf(sbuf, fmt, ap);
80 	va_end(ap);
81 
82 	if (b != NULL) {
83 		strcat(sbuf, " at");
84 		for (u_int i = 0; b->asn_len > i; i++)
85 			sprintf(sbuf + strlen(sbuf), " %02x", b->asn_cptr[i]);
86 	}
87 	strcat(sbuf, "\n");
88 
89 	g_errstr = sbuf;
90 }
91 
92 /**
93  * Encapsulate an ASN.1 parse buffer and the parse header fields.
94  * Constructing parses the header.
95  */
96 struct Asn_value
97 {
98 	/** parse buffer */
99 	struct asn_buf buf;
100 
101 	/** error from header parsing */
102 	asn_err err;
103 
104 	/** ASN.1 tag byte */
105 	uint8_t type;
106 
107 	/** value length */
108 	asn_len_t alen;
109 
110 	/**
111 	 * Construct a parse buffer and parse the header.
112 	 *
113 	 * \tparam Tbuf		input buffer type
114 	 *
115 	 * \param ibuf		input buffer
116 	 */
117 	template<typename Tbuf>
118 	explicit
119 	Asn_value(const Tbuf &ibuf)
120 	  : buf {mk_asn_buf(ibuf)}, err {asn_get_header(&buf, &type, &alen)}
121 	{
122 	}
123 };
124 
125 /**
126  * Parse the ASN.1 header and check the error code. If the error is not
127  * ASN_ERR_OK then check the error string.
128  *
129  * \tparam Tbuf		input buffer type
130  *
131  * \param buf		input buffer
132  * \param err		expected error code (default ASN_ERR_OK)
133  * \param errstr	expected error string (default empty)
134  *
135  * \return the parse buffer
136  */
137 template<typename Tbuf>
138 static auto
139 check_header(const Tbuf &buf, asn_err err = ASN_ERR_OK,
140   std::string_view errstr = {})
141 {
142 	g_errstr.clear();
143 	auto r = Asn_value(buf);
144 	REQUIRE(r.err == err);
145 	if (r.err != ASN_ERR_OK)
146 		REQUIRE(g_errstr == errstr);
147 	else
148 		REQUIRE(g_errstr == "");
149 	return r;
150 }
151 
152 /**
153  * Parse the ASN.1 header and expect it not to fail. The check the tag.
154  *
155  * \tparam Tbuf		input buffer type
156  *
157  * \param buf		input buffer
158  * \param tag		expected type tag
159  *
160  * \return the parse buffer
161  */
162 template<typename Tbuf>
163 static auto
164 check_header(const Tbuf &buf, uint8_t type)
165 {
166 	auto r = check_header(buf);
167 	REQUIRE(r.type == type);
168 	return r;
169 }
170 
171 /**
172  * Parse the ASN.1 header and expect it not to fail. The check the tag and
173  * the length.
174  *
175  * \tparam Tbuf		input buffer type
176  *
177  * \param buf		input buffer
178  * \param tag		expected type tag
179  * \param alen		expected value length
180  *
181  * \return the parse buffer
182  */
183 template<typename Tbuf>
184 static auto
185 check_header(const Tbuf &buf, uint8_t type, asn_len_t alen)
186 {
187 	auto r = check_header(buf);
188 	REQUIRE(r.type == type);
189 	REQUIRE(r.alen == alen);
190 	return r;
191 }
192 
193 template<typename Tbuf>
194 static void
195 check_buf(const asn_buf &s, const Tbuf &exp, bool print = false)
196 {
197 	if (print) {
198 			for (auto c : exp)
199 				std::printf(":%02x", c);
200 			std::printf("\n");
201 
202 			for (size_t i = 0; i < size(exp); i++)
203 				std::printf(":%02x", s.asn_ptr[i]);
204 			std::printf("\n");
205 	}
206 	REQUIRE(std::equal(begin(exp), end(exp), s.asn_ptr));
207 }
208 
209 TEST_CASE("ASN.1 header parsing", "[asn1][parse]")
210 {
211 	asn_error = save_g_errstr;
212 
213 	SECTION("empty buffer") {
214 		check_header(std::vector<u_char>{}, ASN_ERR_EOBUF,
215 			"no identifier for header at\n");
216 	}
217 	SECTION("tag too large") {
218 		check_header("x1f:06:01:7f"_cbuf, ASN_ERR_FAILED,
219 			"tags > 0x1e not supported (0x1f) at 1f 06 01 7f\n");
220 	}
221 	SECTION("no length field") {
222 		check_header("x46"_cbuf, ASN_ERR_EOBUF, "no length field at\n");
223 	}
224 	SECTION("indefinite length") {
225 		check_header("x46:80:02:04:06"_cbuf, ASN_ERR_FAILED,
226 			"indefinite length not supported at 02 04 06\n");
227 	}
228 	SECTION("long length") {
229 		check_header("x46:83:00:00:02:7f:12"_cbuf, ASN_ERR_FAILED,
230 			"long length too long (3) at 00 00 02 7f 12\n");
231 	}
232 	SECTION("truncated length field") {
233 		check_header("x46:82:00"_cbuf, ASN_ERR_EOBUF,
234 			"long length truncated at 00\n");
235 	}
236 	SECTION("correct long length") {
237 		check_header("x04:81:00"_cbuf, ASN_TYPE_OCTETSTRING, 0);
238 #ifndef BOGUS_CVE_2019_5610_FIX
239 		check_header("x04:81:04:00"_cbuf, ASN_TYPE_OCTETSTRING, 4);
240 		check_header("x04:81:ff:00"_cbuf, ASN_TYPE_OCTETSTRING, 255);
241 #endif
242 		check_header("x04:82:00:00"_cbuf, ASN_TYPE_OCTETSTRING, 0);
243 #ifndef BOGUS_CVE_2019_5610_FIX
244 		check_header("x04:82:00:80"_cbuf, ASN_TYPE_OCTETSTRING, 128);
245 		check_header("x04:82:01:80"_cbuf, ASN_TYPE_OCTETSTRING, 384);
246 		check_header("x04:82:ff:ff"_cbuf, ASN_TYPE_OCTETSTRING, 65535);
247 #endif
248 	}
249 	SECTION("short length") {
250 		check_header("x04:00:00"_cbuf, ASN_TYPE_OCTETSTRING, 0);
251 		check_header("x04:01:00"_cbuf, ASN_TYPE_OCTETSTRING, 1);
252 #ifndef BOGUS_CVE_2019_5610_FIX
253 		check_header("x04:40:00"_cbuf, ASN_TYPE_OCTETSTRING, 64);
254 		check_header("x04:7f:00"_cbuf, ASN_TYPE_OCTETSTRING, 127);
255 #endif
256 	}
257 }
258 
259 TEST_CASE("ASN.1 header building", "[asn1][build]")
260 {
261 	asn_error = save_g_errstr;
262 
263 	const auto conv_err = [] (asn_len_t alen, asn_len_t vlen, uint8_t type,
264 	  asn_err err, std::string_view errstr) {
265 		auto b = mk_asn_buf(alen);
266 		g_errstr.clear();
267 		REQUIRE(asn_put_header(&b, type, vlen) == err);
268 		REQUIRE(g_errstr == errstr);
269 	};
270 
271 	const auto conv = [] (asn_len_t alen, asn_len_t vlen, uint8_t type,
272 	  const auto &cbuf) {
273 		auto b = mk_asn_buf(alen);
274 		auto t = b;
275 		REQUIRE(asn_put_header(&b, type, vlen) == ASN_ERR_OK);
276 		REQUIRE(b.asn_len == (size_t)0);
277 		check_buf(t, cbuf);
278 	};
279 
280 	SECTION("no space for tag") {
281 		conv_err(0, 0, ASN_TYPE_OCTETSTRING, ASN_ERR_EOBUF, "");
282 	}
283 	SECTION("no space for length") {
284 		conv_err(1, 0, ASN_TYPE_OCTETSTRING, ASN_ERR_EOBUF, "");
285 		conv_err(2, 128, ASN_TYPE_OCTETSTRING, ASN_ERR_EOBUF, "");
286 	}
287 	SECTION("bad tag") {
288 		conv_err(2, 0, 0x1f, ASN_ERR_FAILED,
289 		  "types > 0x1e not supported (0x1f)\n");
290 		conv_err(2, 0, 0xff, ASN_ERR_FAILED,
291 		  "types > 0x1e not supported (0x1f)\n");
292 	}
293 	SECTION("ok") {
294 		conv(2, 0, ASN_TYPE_OCTETSTRING, "x04:00"_cbuf);
295 	}
296 }
297 
298 TEST_CASE("Counter64 parsing", "[asn1][parse]")
299 {
300 	asn_error = save_g_errstr;
301 
302 	/**
303 	 * Sucessfully parse a COUNTER64 value.
304 	 *
305 	 * \param buf	buffer to parse
306 	 * \param xval	expected value
307 	 */
308 	const auto conv = [] (const auto &buf, uint64_t xval) {
309 		auto r = check_header(buf, ASN_APP_COUNTER64 | ASN_CLASS_APPLICATION);
310 
311 		uint64_t val;
312 		REQUIRE(asn_get_counter64_raw(&r.buf, r.alen, &val) == ASN_ERR_OK);
313 		REQUIRE(val == xval);
314 	};
315 
316 	/**
317 	 * Parse COUNTER64 with error.
318 	 *
319 	 * \param buf	buffer to parse
320 	 * \param err	expected error from value parser
321 	 * \param errstr expected error string
322 	 */
323 	const auto conv_err = [] (const auto &buf, asn_err err,
324 	    std::string_view errstr) {
325 		auto r = check_header(buf, ASN_APP_COUNTER64 | ASN_CLASS_APPLICATION);
326 
327 		g_errstr.clear();
328 		uint64_t val;
329 		REQUIRE(asn_get_counter64_raw(&r.buf, r.alen, &val) == err);
330 		REQUIRE(g_errstr == errstr);
331 	};
332 
333 	SECTION("correct encoding") {
334 
335 		conv("x46:01:00"_cbuf,										   0x0ULL);
336 		conv("x46:01:01"_cbuf,										   0x1ULL);
337 		conv("x46:01:7f"_cbuf,										  0x7fULL);
338 
339 		conv("x46:02:00:80"_cbuf,									  0x80ULL);
340 		conv("x46:02:00:ff"_cbuf,									  0xffULL);
341 		conv("x46:02:7f:ff"_cbuf,									0x7fffULL);
342 
343 		conv("x46:03:00:80:00"_cbuf,		    					0x8000ULL);
344 		conv("x46:03:00:ff:ff"_cbuf,		    					0xffffULL);
345 		conv("x46:03:7f:ff:ff"_cbuf,							  0x7fffffULL);
346 
347 		conv("x46:04:00:80:00:00"_cbuf,							  0x800000ULL);
348 		conv("x46:04:00:ff:ff:ff"_cbuf,							  0xffffffULL);
349 		conv("x46:04:7f:ff:ff:ff"_cbuf,							0x7fffffffULL);
350 
351 		conv("x46:05:00:80:00:00:00"_cbuf,						0x80000000ULL);
352 		conv("x46:05:00:ff:ff:ff:ff"_cbuf,					    0xffffffffULL);
353 		conv("x46:05:7f:ff:ff:ff:ff"_cbuf,					  0x7fffffffffULL);
354 
355 		conv("x46:06:00:80:00:00:00:00"_cbuf,				  0x8000000000ULL);
356 		conv("x46:06:00:ff:ff:ff:ff:ff"_cbuf,				  0xffffffffffULL);
357 		conv("x46:06:7f:ff:ff:ff:ff:ff"_cbuf,				0x7fffffffffffULL);
358 
359 		conv("x46:07:00:80:00:00:00:00:00"_cbuf,		    0x800000000000ULL);
360 		conv("x46:07:00:ff:ff:ff:ff:ff:ff"_cbuf,		    0xffffffffffffULL);
361 		conv("x46:07:7f:ff:ff:ff:ff:ff:ff"_cbuf,		  0x7fffffffffffffULL);
362 
363 		conv("x46:08:00:80:00:00:00:00:00:00"_cbuf,		  0x80000000000000ULL);
364 		conv("x46:08:00:ff:ff:ff:ff:ff:ff:ff"_cbuf,		  0xffffffffffffffULL);
365 		conv("x46:08:7f:ff:ff:ff:ff:ff:ff:ff"_cbuf,		0x7fffffffffffffffULL);
366 
367 		conv("x46:09:00:80:00:00:00:00:00:00:00"_cbuf,	0x8000000000000000ULL);
368 		conv("x46:09:00:ff:ff:ff:ff:ff:ff:ff:ff"_cbuf,	0xffffffffffffffffULL);
369 	}
370 
371 	SECTION("zero length") {
372 		conv_err("x46:00"_cbuf, ASN_ERR_BADLEN,
373 			"zero-length integer at\n");
374 	}
375 
376 	SECTION("non minimal encoding") {
377 		conv_err("x46:02:00:00"_cbuf, ASN_ERR_BADLEN,
378 		    "non-minimal unsigned at 00 00\n");
379 		conv_err("x46:02:00:7f"_cbuf, ASN_ERR_BADLEN,
380 		    "non-minimal unsigned at 00 7f\n");
381 		conv_err("x46:03:00:00:80"_cbuf, ASN_ERR_BADLEN,
382 		    "non-minimal unsigned at 00 00 80\n");
383 		conv_err("x46:04:00:00:80:00"_cbuf, ASN_ERR_BADLEN,
384 		    "non-minimal unsigned at 00 00 80 00\n");
385 		conv_err("x46:0a:00:00:00:00:00:00:00:00:00:00"_cbuf, ASN_ERR_BADLEN,
386 			"non-minimal unsigned at 00 00 00 00 00 00 00 00 00 00\n");
387 		conv_err("x46:0a:00:01:00:00:00:00:00:00:00:00"_cbuf, ASN_ERR_BADLEN,
388 			"non-minimal unsigned at 00 01 00 00 00 00 00 00 00 00\n");
389 	}
390 
391 	SECTION("out of range") {
392 		conv_err("x46:09:01:00:00:00:00:00:00:00:00"_cbuf, ASN_ERR_RANGE,
393 			"unsigned too large or negative at 01 00 00 00 00 00 00 00 00\n");
394 		conv_err("x46:0a:01:00:00:00:00:00:00:00:00:00"_cbuf, ASN_ERR_RANGE,
395 			"unsigned too large or negative at 01 00 00 00 00 00 00 00 00 00\n");
396 		conv_err("x46:01:80"_cbuf, ASN_ERR_RANGE,
397 			"unsigned too large or negative at 80\n");
398 		conv_err("x46:02:80:00"_cbuf, ASN_ERR_RANGE,
399 			"unsigned too large or negative at 80 00\n");
400 		conv_err("x46:03:80:00:00"_cbuf, ASN_ERR_RANGE,
401 			"unsigned too large or negative at 80 00 00\n");
402 	}
403 
404 #ifndef	BOGUS_CVE_2019_5610_FIX
405 	SECTION("truncated value") {
406 		conv_err("x46:02:00"_cbuf, ASN_ERR_EOBUF,
407 			"truncated integer at 00\n");
408 		conv_err("x46:09:00:80:00:00:00"_cbuf, ASN_ERR_EOBUF,
409 			"truncated integer at 00 80 00 00 00\n");
410 		conv_err("x46:09:00:ff:ff:ff:ff:ff:ff:ff"_cbuf, ASN_ERR_EOBUF,
411 			"truncated integer at 00 ff ff ff ff ff ff ff\n");
412 	}
413 #endif
414 }
415 
416 TEST_CASE("Counter64 building", "[asn1][build]")
417 {
418 	asn_error = save_g_errstr;
419 
420 	const auto conv = [] (asn_len_t alen, uint64_t val, const auto &buf) {
421 		auto b = mk_asn_buf(alen);
422 		auto s = b;
423 		REQUIRE(asn_put_counter64(&b, val) == ASN_ERR_OK);
424 		REQUIRE(b.asn_len == (size_t)0);
425 		check_buf(s, buf);
426 	};
427 
428 	const auto conv_err = [] (asn_len_t alen, uint64_t val, asn_err err,
429 	  std::string_view errstr) {
430 		auto b = mk_asn_buf(alen);
431 		g_errstr.clear();
432 		REQUIRE(asn_put_counter64(&b, val) == err);
433 		REQUIRE(g_errstr == errstr);
434 	};
435 
436 	conv(3,  0x0, "x46:01:00"_cbuf);
437 	conv(3,  0x1, "x46:01:01"_cbuf);
438 	conv(3, 0x7f, "x46:01:7f"_cbuf);
439 
440 	conv(4,   0x80, "x46:02:00:80"_cbuf);
441 	conv(4,   0xff, "x46:02:00:ff"_cbuf);
442 	conv(4, 0x7fff, "x46:02:7f:ff"_cbuf);
443 
444 	conv(5,   0x8000, "x46:03:00:80:00"_cbuf);
445 	conv(5,   0xffff, "x46:03:00:ff:ff"_cbuf);
446 	conv(5, 0x7fffff, "x46:03:7f:ff:ff"_cbuf);
447 
448 	conv(6,   0x800000, "x46:04:00:80:00:00"_cbuf);
449 	conv(6,   0xffffff, "x46:04:00:ff:ff:ff"_cbuf);
450 	conv(6, 0x7fffffff, "x46:04:7f:ff:ff:ff"_cbuf);
451 
452 	conv(7,   0x80000000, "x46:05:00:80:00:00:00"_cbuf);
453 	conv(7,   0xffffffff, "x46:05:00:ff:ff:ff:ff"_cbuf);
454 	conv(7, 0x7fffffffff, "x46:05:7f:ff:ff:ff:ff"_cbuf);
455 
456 	conv(8,   0x8000000000, "x46:06:00:80:00:00:00:00"_cbuf);
457 	conv(8,   0xffffffffff, "x46:06:00:ff:ff:ff:ff:ff"_cbuf);
458 	conv(8, 0x7fffffffffff, "x46:06:7f:ff:ff:ff:ff:ff"_cbuf);
459 
460 	conv(9,   0x800000000000, "x46:07:00:80:00:00:00:00:00"_cbuf);
461 	conv(9,   0xffffffffffff, "x46:07:00:ff:ff:ff:ff:ff:ff"_cbuf);
462 	conv(9, 0x7fffffffffffff, "x46:07:7f:ff:ff:ff:ff:ff:ff"_cbuf);
463 
464 	conv(10,   0x80000000000000, "x46:08:00:80:00:00:00:00:00:00"_cbuf);
465 	conv(10,   0xffffffffffffff, "x46:08:00:ff:ff:ff:ff:ff:ff:ff"_cbuf);
466 	conv(10, 0x7fffffffffffffff, "x46:08:7f:ff:ff:ff:ff:ff:ff:ff"_cbuf);
467 
468 	conv(11,   0x8000000000000000, "x46:09:00:80:00:00:00:00:00:00:00"_cbuf);
469 	conv(11,   0xffffffffffffffff, "x46:09:00:ff:ff:ff:ff:ff:ff:ff:ff"_cbuf);
470 
471 	SECTION("empty buffer") {
472 		conv_err(0, 0, ASN_ERR_EOBUF, "");
473 	}
474 	SECTION("buffer too short for length field") {
475 		conv_err(1, 0, ASN_ERR_EOBUF, "");
476 	}
477 	SECTION("buffer too short") {
478 		conv_err(2, 0, ASN_ERR_EOBUF, "");
479 		conv_err(3, 0x80, ASN_ERR_EOBUF, "");
480 		conv_err(4, 0x8000, ASN_ERR_EOBUF, "");
481 		conv_err(5, 0x800000, ASN_ERR_EOBUF, "");
482 		conv_err(6, 0x80000000, ASN_ERR_EOBUF, "");
483 		conv_err(7, 0x8000000000, ASN_ERR_EOBUF, "");
484 		conv_err(8, 0x800000000000, ASN_ERR_EOBUF, "");
485 		conv_err(9, 0x80000000000000, ASN_ERR_EOBUF, "");
486 		conv_err(10, 0x8000000000000000, ASN_ERR_EOBUF, "");
487 	}
488 }
489 
490 TEST_CASE("Unsigned32 parsing", "[asn1][parse]")
491 {
492 	asn_error = save_g_errstr;
493 
494 	/**
495 	 * Sucessfully parse a COUNTER value.
496 	 *
497 	 * \param buf	buffer to parse
498 	 * \param xval	expected value
499 	 */
500 	const auto conv = [] (const auto &buf, uint32_t xval) {
501 		auto r = check_header(buf, ASN_APP_COUNTER | ASN_CLASS_APPLICATION);
502 
503 		uint32_t val;
504 		REQUIRE(asn_get_uint32_raw(&r.buf, r.alen, &val) == ASN_ERR_OK);
505 		REQUIRE(val == xval);
506 	};
507 
508 	/**
509 	 * Parse COUNTER with error.
510 	 *
511 	 * \param buf	buffer to parse
512 	 * \param err	expected error from value parser
513 	 * \param errstr expected error string
514 	 */
515 	const auto conv_err = [] (const auto &buf, asn_err err,
516 	    std::string_view errstr) {
517 		auto r = check_header(buf, ASN_APP_COUNTER | ASN_CLASS_APPLICATION);
518 
519 		g_errstr.clear();
520 		uint32_t val;
521 		REQUIRE(asn_get_uint32_raw(&r.buf, r.alen, &val) == err);
522 		REQUIRE(g_errstr == errstr);
523 	};
524 
525 	SECTION("correct encoding") {
526 		conv("x41:01:00"_cbuf,			   0x0U);
527 		conv("x41:01:01"_cbuf,			   0x1U);
528 		conv("x41:01:7f"_cbuf,			   0x7fU);
529 
530 		conv("x41:02:00:80"_cbuf,		   0x80U);
531 		conv("x41:02:00:ff"_cbuf,		   0xffU);
532 		conv("x41:02:7f:ff"_cbuf,		   0x7fffU);
533 
534 		conv("x41:03:00:80:00"_cbuf,	   0x8000U);
535 		conv("x41:03:00:ff:ff"_cbuf,	   0xffffU);
536 		conv("x41:03:7f:ff:ff"_cbuf,	   0x7fffffU);
537 
538 		conv("x41:04:00:80:00:00"_cbuf,	   0x800000U);
539 		conv("x41:04:00:ff:ff:ff"_cbuf,	   0xffffffU);
540 		conv("x41:04:7f:ff:ff:ff"_cbuf,	   0x7fffffffU);
541 
542 		conv("x41:05:00:80:00:00:00"_cbuf, 0x80000000U);
543 		conv("x41:05:00:ff:ff:ff:ff"_cbuf, 0xffffffffU);
544 	}
545 	SECTION("zero length") {
546 
547 		conv_err("x41:00"_cbuf, ASN_ERR_BADLEN,
548 			"zero-length integer at\n");
549 	}
550 
551 	SECTION("non minimal encoding") {
552 		conv_err("x41:02:00:00"_cbuf, ASN_ERR_BADLEN,
553 		    "non-minimal unsigned at 00 00\n");
554 		conv_err("x41:02:00:7f"_cbuf, ASN_ERR_BADLEN,
555 		    "non-minimal unsigned at 00 7f\n");
556 		conv_err("x41:03:00:00:80"_cbuf, ASN_ERR_BADLEN,
557 		    "non-minimal unsigned at 00 00 80\n");
558 		conv_err("x41:04:00:00:80:00"_cbuf, ASN_ERR_BADLEN,
559 		    "non-minimal unsigned at 00 00 80 00\n");
560 		conv_err("x41:06:00:00:00:00:00:00"_cbuf, ASN_ERR_BADLEN,
561 			"non-minimal unsigned at 00 00 00 00 00 00\n");
562 		conv_err("x41:06:00:01:00:00:00:00"_cbuf, ASN_ERR_BADLEN,
563 			"non-minimal unsigned at 00 01 00 00 00 00\n");
564 	}
565 
566 	SECTION("out of range") {
567 		conv_err("x41:05:01:00:00:00:00"_cbuf,
568 			ASN_ERR_RANGE, "uint32 too large 4294967296 at\n");
569 		conv_err("x41:06:01:00:00:00:00:00"_cbuf,
570 			ASN_ERR_RANGE, "uint32 too large 1099511627776 at\n");
571 		conv_err("x41:01:80"_cbuf,
572 			ASN_ERR_RANGE, "unsigned too large or negative at 80\n");
573 		conv_err("x41:02:80:00"_cbuf,
574 			ASN_ERR_RANGE, "unsigned too large or negative at 80 00\n");
575 		conv_err("x41:03:80:00:00"_cbuf,
576 			ASN_ERR_RANGE, "unsigned too large or negative at 80 00 00\n");
577 	}
578 
579 #ifndef	BOGUS_CVE_2019_5610_FIX
580 	SECTION("truncated value") {
581 		conv_err("x41:01"_cbuf, ASN_ERR_EOBUF,
582 			"truncated integer at\n");
583 		conv_err("x41:02:01"_cbuf, ASN_ERR_EOBUF,
584 			"truncated integer at 01\n");
585 		conv_err("x41:05:00:80:"_cbuf, ASN_ERR_EOBUF,
586 			"truncated integer at 00 80\n");
587 		conv_err("x41:05:00:ff:ff:ff"_cbuf, ASN_ERR_EOBUF,
588 			"truncated integer at 00 ff ff ff\n");
589 	}
590 #endif
591 }
592 
593 TEST_CASE("Unsigned32 building", "[asn1][build]")
594 {
595 	asn_error = save_g_errstr;
596 
597 	const auto conv = [] (asn_len_t alen, uint32_t val, const auto &buf) {
598 		auto b = mk_asn_buf(alen);
599 		auto s = b;
600 		REQUIRE(asn_put_uint32(&b, ASN_APP_COUNTER, val) == ASN_ERR_OK);
601 		REQUIRE(b.asn_len == (size_t)0);
602 		check_buf(s, buf);
603 	};
604 
605 	const auto conv_err = [] (asn_len_t alen, uint32_t val, asn_err err,
606 	  std::string_view errstr) {
607 		auto b = mk_asn_buf(alen);
608 		g_errstr.clear();
609 		REQUIRE(asn_put_uint32(&b, ASN_APP_COUNTER, val) == err);
610 		REQUIRE(g_errstr == errstr);
611 	};
612 
613 	conv(3,  0x0, "x41:01:00"_cbuf);
614 	conv(3,  0x1, "x41:01:01"_cbuf);
615 	conv(3, 0x7f, "x41:01:7f"_cbuf);
616 
617 	conv(4,   0x80, "x41:02:00:80"_cbuf);
618 	conv(4,   0xff, "x41:02:00:ff"_cbuf);
619 	conv(4, 0x7fff, "x41:02:7f:ff"_cbuf);
620 
621 	conv(5,   0x8000, "x41:03:00:80:00"_cbuf);
622 	conv(5,   0xffff, "x41:03:00:ff:ff"_cbuf);
623 	conv(5, 0x7fffff, "x41:03:7f:ff:ff"_cbuf);
624 
625 	conv(6,   0x800000, "x41:04:00:80:00:00"_cbuf);
626 	conv(6,   0xffffff, "x41:04:00:ff:ff:ff"_cbuf);
627 	conv(6, 0x7fffffff, "x41:04:7f:ff:ff:ff"_cbuf);
628 
629 	conv(7,   0x80000000, "x41:05:00:80:00:00:00"_cbuf);
630 	conv(7,   0xffffffff, "x41:05:00:ff:ff:ff:ff"_cbuf);
631 
632 	SECTION("empty buffer") {
633 		conv_err(0, 0, ASN_ERR_EOBUF, "");
634 	}
635 	SECTION("buffer too short for length field") {
636 		conv_err(1, 0, ASN_ERR_EOBUF, "");
637 	}
638 	SECTION("buffer too short") {
639 		conv_err(2, 0, ASN_ERR_EOBUF, "");
640 		conv_err(3, 0x80, ASN_ERR_EOBUF, "");
641 		conv_err(4, 0x8000, ASN_ERR_EOBUF, "");
642 		conv_err(5, 0x800000, ASN_ERR_EOBUF, "");
643 		conv_err(6, 0x80000000, ASN_ERR_EOBUF, "");
644 	}
645 }
646 
647 TEST_CASE("Integer parsing", "[asn1][parse]")
648 {
649 	asn_error = save_g_errstr;
650 
651 	/**
652 	 * Sucessfully parse a INTEGER value.
653 	 *
654 	 * \param buf	buffer to parse
655 	 * \param xval	expected value
656 	 */
657 	const auto conv = [] (const auto &buf, int32_t xval) {
658 		auto r = check_header(buf, ASN_TYPE_INTEGER);
659 
660 		int32_t val;
661 		REQUIRE(asn_get_integer_raw(&r.buf, r.alen, &val) == ASN_ERR_OK);
662 		REQUIRE(val == xval);
663 	};
664 
665 	/**
666 	 * Parse INTEGER with error.
667 	 *
668 	 * \param buf	buffer to parse
669 	 * \param err	expected error from value parser
670 	 * \param errstr expected error string
671 	 */
672 	const auto conv_err = [] (const auto &buf, asn_err err,
673 	    std::string_view errstr) {
674 		auto r = check_header(buf, ASN_TYPE_INTEGER);
675 
676 		g_errstr.clear();
677 		int32_t val;
678 		REQUIRE(asn_get_integer_raw(&r.buf, r.alen, &val) == err);
679 		REQUIRE(g_errstr == errstr);
680 	};
681 
682 	SECTION("correct encoding") {
683 		conv("x02:01:00"_cbuf,					   0x0);
684 		conv("x02:01:01"_cbuf,					   0x1);
685 		conv("x02:01:7f"_cbuf,					  0x7f);
686 		conv("x02:01:ff"_cbuf,					  -0x1);
687 		conv("x02:01:80"_cbuf,					 -0x80);
688 
689 		conv("x02:02:00:80"_cbuf,				  0x80);
690 		conv("x02:02:00:ff"_cbuf,				  0xff);
691 		conv("x02:02:7f:ff"_cbuf,				0x7fff);
692 		conv("x02:02:ff:7f"_cbuf,				 -0x81);
693 		conv("x02:02:ff:01"_cbuf,				 -0xff);
694 		conv("x02:02:ff:00"_cbuf,				-0x100);
695 		conv("x02:02:80:00"_cbuf,			   -0x8000);
696 
697 		conv("x02:03:00:80:00"_cbuf,			 0x8000);
698 		conv("x02:03:00:ff:ff"_cbuf,			 0xffff);
699 		conv("x02:03:7f:ff:ff"_cbuf,		   0x7fffff);
700 		conv("x02:03:ff:7f:ff"_cbuf,			-0x8001);
701 		conv("x02:03:ff:00:01"_cbuf,			-0xffff);
702 		conv("x02:03:ff:00:00"_cbuf,		   -0x10000);
703 		conv("x02:03:80:00:00"_cbuf,		  -0x800000);
704 
705 		conv("x02:04:00:80:00:00"_cbuf,		   0x800000);
706 		conv("x02:04:00:ff:ff:ff"_cbuf,		   0xffffff);
707 		conv("x02:04:7f:ff:ff:ff"_cbuf,		 0x7fffffff);
708 		conv("x02:04:ff:7f:ff:ff"_cbuf,		  -0x800001);
709 		conv("x02:04:ff:00:00:01"_cbuf,		  -0xffffff);
710 		conv("x02:04:ff:00:00:00"_cbuf,		 -0x1000000);
711 		conv("x02:04:80:00:00:00"_cbuf,		-0x80000000);
712 	}
713 
714 	SECTION("zero length") {
715 		conv_err("x02:00"_cbuf, ASN_ERR_BADLEN,
716 			"zero-length integer at\n");
717 	}
718 	SECTION("too long") {
719 		conv_err("x02:05:01:02:03:04:05"_cbuf, ASN_ERR_BADLEN,
720 			"integer too long at\n");
721 	}
722 
723 	SECTION("non minimal encoding") {
724 		conv_err("x02:02:00:00"_cbuf, ASN_ERR_BADLEN,
725 		    "non-minimal integer at 00 00\n");
726 		conv_err("x02:02:00:7f"_cbuf, ASN_ERR_BADLEN,
727 		    "non-minimal integer at 00 7f\n");
728 		conv_err("x02:03:00:00:80"_cbuf, ASN_ERR_BADLEN,
729 		    "non-minimal integer at 00 00 80\n");
730 		conv_err("x02:04:00:00:80:00"_cbuf, ASN_ERR_BADLEN,
731 		    "non-minimal integer at 00 00 80 00\n");
732 		conv_err("x02:06:00:00:00:00:00:00"_cbuf, ASN_ERR_BADLEN,
733 			"non-minimal integer at 00 00 00 00 00 00\n");
734 		conv_err("x02:06:00:01:00:00:00:00"_cbuf, ASN_ERR_BADLEN,
735 			"non-minimal integer at 00 01 00 00 00 00\n");
736 		conv_err("x02:02:ff:80"_cbuf, ASN_ERR_BADLEN,
737 		    "non-minimal integer at ff 80\n");
738 		conv_err("x02:02:ff:ff"_cbuf, ASN_ERR_BADLEN,
739 		    "non-minimal integer at ff ff\n");
740 		conv_err("x02:03:ff:80:00"_cbuf, ASN_ERR_BADLEN,
741 		    "non-minimal integer at ff 80 00\n");
742 		conv_err("x02:03:ff:ff:ff"_cbuf, ASN_ERR_BADLEN,
743 		    "non-minimal integer at ff ff ff\n");
744 		conv_err("x02:04:ff:80:00:00"_cbuf, ASN_ERR_BADLEN,
745 		    "non-minimal integer at ff 80 00 00\n");
746 		conv_err("x02:04:ff:ff:ff:ff"_cbuf, ASN_ERR_BADLEN,
747 		    "non-minimal integer at ff ff ff ff\n");
748 		conv_err("x02:06:ff:80:00:00:00:00"_cbuf, ASN_ERR_BADLEN,
749 		    "non-minimal integer at ff 80 00 00 00 00\n");
750 		conv_err("x02:06:ff:ff:ff:ff:ff:ff"_cbuf, ASN_ERR_BADLEN,
751 		    "non-minimal integer at ff ff ff ff ff ff\n");
752 	}
753 
754 #ifndef	BOGUS_CVE_2019_5610_FIX
755 	SECTION("truncated value") {
756 		conv_err("x02:01"_cbuf, ASN_ERR_EOBUF,
757 			"truncated integer at\n");
758 		conv_err("x02:02:ff"_cbuf, ASN_ERR_EOBUF,
759 			"truncated integer at ff\n");
760 		conv_err("x02:05:ff:00:03:01"_cbuf, ASN_ERR_EOBUF,
761 			"truncated integer at ff 00 03 01\n");
762 		conv_err("x02:04:7f:ff:"_cbuf, ASN_ERR_EOBUF,
763 			"truncated integer at 7f ff\n");
764 		conv_err("x02:04:80:00:00"_cbuf, ASN_ERR_EOBUF,
765 			"truncated integer at 80 00 00\n");
766 	}
767 #endif
768 }
769 
770 TEST_CASE("Integer32 building", "[asn1][build]")
771 {
772 	asn_error = save_g_errstr;
773 
774 	const auto conv = [] (asn_len_t alen, int32_t val, const auto &buf) {
775 		auto b = mk_asn_buf(alen);
776 		auto s = b;
777 		REQUIRE(asn_put_integer(&b, val) == ASN_ERR_OK);
778 		REQUIRE(b.asn_len == (size_t)0);
779 		check_buf(s, buf);
780 	};
781 
782 	const auto conv_err = [] (asn_len_t alen, int32_t val, asn_err err,
783 	  std::string_view errstr) {
784 		auto b = mk_asn_buf(alen);
785 		g_errstr.clear();
786 		REQUIRE(asn_put_integer(&b, val) == err);
787 		REQUIRE(g_errstr == errstr);
788 	};
789 
790 	conv(3,			 0x0, "x02:01:00"_cbuf);
791 	conv(3,			 0x1, "x02:01:01"_cbuf);
792 	conv(3,			0x7f, "x02:01:7f"_cbuf);
793 	conv(3,			-0x1, "x02:01:ff"_cbuf);
794 	conv(3,		   -0x80, "x02:01:80"_cbuf);
795 
796 	conv(4,			0x80, "x02:02:00:80"_cbuf);
797 	conv(4,			0xff, "x02:02:00:ff"_cbuf);
798 	conv(4,		  0x7fff, "x02:02:7f:ff"_cbuf);
799 	conv(4,		   -0x81, "x02:02:ff:7f"_cbuf);
800 	conv(4,		   -0xff, "x02:02:ff:01"_cbuf);
801 	conv(4,		  -0x100, "x02:02:ff:00"_cbuf);
802 	conv(4,		 -0x8000, "x02:02:80:00"_cbuf);
803 
804 	conv(5,		 0x8000, "x02:03:00:80:00"_cbuf);
805 	conv(5,		 0xffff, "x02:03:00:ff:ff"_cbuf);
806 	conv(5,	   0x7fffff, "x02:03:7f:ff:ff"_cbuf);
807 	conv(5,		-0x8001, "x02:03:ff:7f:ff"_cbuf);
808 	conv(5,		-0xffff, "x02:03:ff:00:01"_cbuf);
809 	conv(5,	   -0x10000, "x02:03:ff:00:00"_cbuf);
810 	conv(5,	  -0x800000, "x02:03:80:00:00"_cbuf);
811 
812 	conv(6,	   0x800000, "x02:04:00:80:00:00"_cbuf);
813 	conv(6,	   0xffffff, "x02:04:00:ff:ff:ff"_cbuf);
814 	conv(6,	 0x7fffffff, "x02:04:7f:ff:ff:ff"_cbuf);
815 	conv(6,	  -0x800001, "x02:04:ff:7f:ff:ff"_cbuf);
816 	conv(6,	  -0xffffff, "x02:04:ff:00:00:01"_cbuf);
817 	conv(6,	 -0x1000000, "x02:04:ff:00:00:00"_cbuf);
818 	conv(6,	-0x80000000, "x02:04:80:00:00:00"_cbuf);
819 
820 	SECTION("empty buffer") {
821 		conv_err(0, 0, ASN_ERR_EOBUF, "");
822 	}
823 	SECTION("buffer too short for length field") {
824 		conv_err(1, 0, ASN_ERR_EOBUF, "");
825 	}
826 	SECTION("buffer too short") {
827 		conv_err(2, 0, ASN_ERR_EOBUF, "");
828 		conv_err(3, 0xff, ASN_ERR_EOBUF, "");
829 		conv_err(4, 0xffff, ASN_ERR_EOBUF, "");
830 		conv_err(5, 0xffffff, ASN_ERR_EOBUF, "");
831 		conv_err(5, 0x7fffffff, ASN_ERR_EOBUF, "");
832 		conv_err(2, -0x80, ASN_ERR_EOBUF, "");
833 		conv_err(3, -0x8000, ASN_ERR_EOBUF, "");
834 		conv_err(4, -0x800000, ASN_ERR_EOBUF, "");
835 		conv_err(5, -0x80000000, ASN_ERR_EOBUF, "");
836 	}
837 }
838 
839 TEST_CASE("Oid parsing", "[asn1][parse]")
840 {
841 	asn_error = save_g_errstr;
842 
843 	/**
844 	 * Sucessfully parse a INTEGER value.
845 	 *
846 	 * \param buf	buffer to parse
847 	 * \param xval	expected value
848 	 */
849 	const auto conv = [] (const auto &buf, const asn_oid &xval) {
850 		auto r = check_header(buf, ASN_TYPE_OBJID);
851 
852 		struct asn_oid val;
853 		REQUIRE(asn_get_objid_raw(&r.buf, r.alen, &val) == ASN_ERR_OK);
854 		REQUIRE(asn_compare_oid(&val, &xval) == 0);
855 	};
856 
857 	/**
858 	 * Parse INTEGER with error.
859 	 *
860 	 * \param buf	buffer to parse
861 	 * \param err	expected error from value parser
862 	 * \param errstr expected error string
863 	 */
864 	const auto conv_err = [] (const auto &buf, asn_err err,
865 	    std::string_view errstr) {
866 		auto r = check_header(buf, ASN_TYPE_OBJID);
867 
868 		g_errstr.clear();
869 		struct asn_oid val;
870 		REQUIRE(asn_get_objid_raw(&r.buf, r.alen, &val) == err);
871 		REQUIRE(g_errstr == errstr);
872 	};
873 
874 	conv("x06:01:00"_cbuf, asn_oid {2, {0, 0}});
875 	conv("x06:01:28"_cbuf, asn_oid {2, {1, 0}});
876 	conv("x06:01:50"_cbuf, asn_oid {2, {2, 0}});
877 
878 	conv("x06:01:27"_cbuf, asn_oid {2, {0, 39}});
879 	conv("x06:01:4f"_cbuf, asn_oid {2, {1, 39}});
880 	conv("x06:01:7f"_cbuf, asn_oid {2, {2, 47}});
881 
882 	conv("x06:02:81:00"_cbuf, asn_oid {2, {2, 48}});
883 	conv("x06:02:ff:7f"_cbuf, asn_oid {2, {2, 16303}});
884 	conv("x06:03:ff:ff:7f"_cbuf, asn_oid {2, {2, 2097071}});
885 	conv("x06:04:ff:ff:ff:7f"_cbuf, asn_oid {2, {2, 268435375}});
886 	conv("x06:05:8f:ff:ff:ff:7f"_cbuf, asn_oid {2, {2, 4294967215}});
887 
888 	/* maximum OID */
889 	conv("x06:82:02:7b:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f"_cbuf, asn_oid {128, {
890 		2, 4294967215, 4294967295, 4294967295,
891 		4294967295, 4294967295, 4294967295, 4294967295,
892 		4294967295, 4294967295, 4294967295, 4294967295,
893 		4294967295, 4294967295, 4294967295, 4294967295,
894 		4294967295, 4294967295, 4294967295, 4294967295,
895 		4294967295, 4294967295, 4294967295, 4294967295,
896 		4294967295, 4294967295, 4294967295, 4294967295,
897 		4294967295, 4294967295, 4294967295, 4294967295,
898 		4294967295, 4294967295, 4294967295, 4294967295,
899 		4294967295, 4294967295, 4294967295, 4294967295,
900 		4294967295, 4294967295, 4294967295, 4294967295,
901 		4294967295, 4294967295, 4294967295, 4294967295,
902 		4294967295, 4294967295, 4294967295, 4294967295,
903 		4294967295, 4294967295, 4294967295, 4294967295,
904 		4294967295, 4294967295, 4294967295, 4294967295,
905 		4294967295, 4294967295, 4294967295, 4294967295,
906 		4294967295, 4294967295, 4294967295, 4294967295,
907 		4294967295, 4294967295, 4294967295, 4294967295,
908 		4294967295, 4294967295, 4294967295, 4294967295,
909 		4294967295, 4294967295, 4294967295, 4294967295,
910 		4294967295, 4294967295, 4294967295, 4294967295,
911 		4294967295, 4294967295, 4294967295, 4294967295,
912 		4294967295, 4294967295, 4294967295, 4294967295,
913 		4294967295, 4294967295, 4294967295, 4294967295,
914 		4294967295, 4294967295, 4294967295, 4294967295,
915 		4294967295, 4294967295, 4294967295, 4294967295,
916 		4294967295, 4294967295, 4294967295, 4294967295,
917 		4294967295, 4294967295, 4294967295, 4294967295,
918 		4294967295, 4294967295, 4294967295, 4294967295,
919 		4294967295, 4294967295, 4294967295, 4294967295,
920 		4294967295, 4294967295, 4294967295, 4294967295,
921 		4294967295, 4294967295, 4294967295, 4294967295,
922 	}});
923 
924 	SECTION("truncated OID") {
925 #ifndef BOGUS_CVE_2019_5610_FIX
926 		conv_err("x06:02:01"_cbuf, ASN_ERR_EOBUF,
927 			"truncated OBJID at 01\n");
928 #endif
929 		conv_err("x06:01:8f"_cbuf, ASN_ERR_EOBUF,
930 			"unterminated subid at\n");
931 		conv_err("x06:04:07:7f:82:8e"_cbuf, ASN_ERR_EOBUF,
932 			"unterminated subid at\n");
933 	}
934 	SECTION("short OID") {
935 		conv_err("x06:00"_cbuf, ASN_ERR_BADLEN,
936 			"short OBJID at\n");
937 	}
938 	SECTION("too long") {
939 		conv_err("x06:81:80:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c"_cbuf, ASN_ERR_BADLEN, "OID too long (128) at 7c\n");
940 	}
941 	SECTION("subid too large") {
942 		conv_err("x06:06:20:90:82:83:84:75"_cbuf, ASN_ERR_RANGE,
943 			"OID subid too larger at 75\n");
944 	}
945 }
946 
947 TEST_CASE("Objid building", "[asn1][build]")
948 {
949 	asn_error = save_g_errstr;
950 
951 	const auto conv = [] (asn_len_t alen, const asn_oid &val, const auto &buf) {
952 		auto b = mk_asn_buf(alen);
953 		auto s = b;
954 		REQUIRE(asn_put_objid(&b, &val) == ASN_ERR_OK);
955 		REQUIRE(b.asn_len == (size_t)0);
956 		check_buf(s, buf);
957 	};
958 
959 	const auto conv_err = [] (asn_len_t alen, const asn_oid &val, asn_err err,
960 	  std::string_view errstr) {
961 		auto b = mk_asn_buf(alen);
962 		g_errstr.clear();
963 		REQUIRE(asn_put_objid(&b, &val) == err);
964 		REQUIRE(g_errstr == errstr);
965 	};
966 
967 	conv(3, asn_oid {2, {0, 0}}, "x06:01:00"_cbuf);
968 	conv(3, asn_oid {2, {1, 0}}, "x06:01:28"_cbuf);
969 	conv(3, asn_oid {2, {2, 0}}, "x06:01:50"_cbuf);
970 
971 	conv(3, asn_oid {2, {0, 39}}, "x06:01:27"_cbuf);
972 	conv(3, asn_oid {2, {1, 39}}, "x06:01:4f"_cbuf);
973 	conv(3, asn_oid {2, {2, 47}}, "x06:01:7f"_cbuf);
974 
975 	conv(4, asn_oid {2, {2, 48}}, "x06:02:81:00"_cbuf);
976 	conv(4, asn_oid {2, {2, 16303}}, "x06:02:ff:7f"_cbuf);
977 	conv(5, asn_oid {2, {2, 2097071}}, "x06:03:ff:ff:7f"_cbuf);
978 	conv(6, asn_oid {2, {2, 268435375}}, "x06:04:ff:ff:ff:7f"_cbuf);
979 	conv(7, asn_oid {2, {2, 4294967215}}, "x06:05:8f:ff:ff:ff:7f"_cbuf);
980 
981 	SECTION("sub-id too large") {
982 		conv_err(3, asn_oid {2, {3, 0}}, ASN_ERR_RANGE,
983 			"oid out of range (3,0)\n");
984 		conv_err(3, asn_oid {2, {0, 40}}, ASN_ERR_RANGE,
985 			"oid out of range (0,40)\n");
986 		conv_err(3, asn_oid {2, {1, 40}}, ASN_ERR_RANGE,
987 			"oid out of range (1,40)\n");
988 		conv_err(3, asn_oid {2, {2, 4294967216}}, ASN_ERR_RANGE,
989 			"oid out of range (2,4294967216)\n");
990 	}
991 	SECTION("oid too long") {
992 		conv_err(200, asn_oid {129, {}}, ASN_ERR_RANGE,
993 			"oid too long 129\n");
994 	}
995 	SECTION("oid too short") {
996 		conv_err(3, asn_oid {0, {}}, ASN_ERR_RANGE,
997 			"short oid\n");
998 		conv_err(3, asn_oid {1, {0}}, ASN_ERR_RANGE,
999 			"short oid\n");
1000 		conv_err(3, asn_oid {1, {3}}, ASN_ERR_RANGE,
1001 			"oid[0] too large (3)\n");
1002 	}
1003 
1004 	/* maximum OID */
1005 	conv(5 * (128 - 1) + 4, asn_oid {128, {
1006 		2, 4294967215, 4294967295, 4294967295,
1007 		4294967295, 4294967295, 4294967295, 4294967295,
1008 		4294967295, 4294967295, 4294967295, 4294967295,
1009 		4294967295, 4294967295, 4294967295, 4294967295,
1010 		4294967295, 4294967295, 4294967295, 4294967295,
1011 		4294967295, 4294967295, 4294967295, 4294967295,
1012 		4294967295, 4294967295, 4294967295, 4294967295,
1013 		4294967295, 4294967295, 4294967295, 4294967295,
1014 		4294967295, 4294967295, 4294967295, 4294967295,
1015 		4294967295, 4294967295, 4294967295, 4294967295,
1016 		4294967295, 4294967295, 4294967295, 4294967295,
1017 		4294967295, 4294967295, 4294967295, 4294967295,
1018 		4294967295, 4294967295, 4294967295, 4294967295,
1019 		4294967295, 4294967295, 4294967295, 4294967295,
1020 		4294967295, 4294967295, 4294967295, 4294967295,
1021 		4294967295, 4294967295, 4294967295, 4294967295,
1022 		4294967295, 4294967295, 4294967295, 4294967295,
1023 		4294967295, 4294967295, 4294967295, 4294967295,
1024 		4294967295, 4294967295, 4294967295, 4294967295,
1025 		4294967295, 4294967295, 4294967295, 4294967295,
1026 		4294967295, 4294967295, 4294967295, 4294967295,
1027 		4294967295, 4294967295, 4294967295, 4294967295,
1028 		4294967295, 4294967295, 4294967295, 4294967295,
1029 		4294967295, 4294967295, 4294967295, 4294967295,
1030 		4294967295, 4294967295, 4294967295, 4294967295,
1031 		4294967295, 4294967295, 4294967295, 4294967295,
1032 		4294967295, 4294967295, 4294967295, 4294967295,
1033 		4294967295, 4294967295, 4294967295, 4294967295,
1034 		4294967295, 4294967295, 4294967295, 4294967295,
1035 		4294967295, 4294967295, 4294967295, 4294967295,
1036 		4294967295, 4294967295, 4294967295, 4294967295,
1037 		4294967295, 4294967295, 4294967295, 4294967295,
1038 	}}, "x06:82:02:7b:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f"_cbuf);
1039 }
1040 
1041 /* loop tests */
1042