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
32extern "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
45using namespace test::literals;
46
47template<typename T>
48static std::enable_if_t<!std::is_integral_v<T>, asn_buf>
49mk_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
59static asn_buf
60mk_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
70static std::string g_errstr;
71
72static void
73save_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 */
96struct 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 */
137template<typename Tbuf>
138static auto
139check_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 */
162template<typename Tbuf>
163static auto
164check_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 */
183template<typename Tbuf>
184static auto
185check_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
193template<typename Tbuf>
194static void
195check_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
209TEST_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
259TEST_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
298TEST_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
416TEST_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
490TEST_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
593TEST_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
647TEST_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
770TEST_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
839TEST_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
947TEST_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