32 #include <gtest/gtest.h>
36 #include <system_error>
55 using std::runtime_error;
72 using scc::crypto::BasePtr;
74 using CharVec = std::vector<char>;
79 cout <<
"** base dump ***" << endl;
83 cout <<
"** integer dump ***" << endl;
87 cout <<
"** sequence dump ***" << endl;
91 cout <<
"** set dump ***" << endl;
95 TEST(DerTest, low_tag_len_3)
98 CharVec inv = {
'\x8a',
'\x03'};
99 for (
int i = 0; i < 3; i++) inv.push_back((
char)i);
104 cout <<
"** class, id 10, length 3 dump:" << endl;
109 ASSERT_TRUE(r.context_class());
110 ASSERT_EQ(r.id(), 10);
111 ASSERT_EQ(r.pre_len(), 2);
112 ASSERT_EQ(r.len(), 3);
113 for (
int i = 0; i < 3; i++)
115 ASSERT_EQ((
int)(r.data()[i]), i%256);
118 CharVec prev(r.pre_len());
121 for (
size_t i = 0; i < prev.size(); i++)
123 ASSERT_EQ(inv[i], prev[i]);
129 cout <<
"doc before: " << Hex::bin_to_hex(inv) << endl;
130 cout <<
"doc after: " << Hex::bin_to_hex(alld) << endl;
132 ASSERT_EQ(inv, alld);
135 TEST(DerTest, high_tag_length_257)
138 CharVec inv = {
'\x9f',
'\x81',
'\x01',
'\x82',
'\x01',
'\x01'};
139 for (
int i = 0; i < 257; i++) inv.push_back((
char)(i%256));
144 cout <<
"** class, id 129, length 3 dump:" << endl;
149 ASSERT_TRUE(r.context_class());
150 ASSERT_EQ(r.id(), 129);
151 ASSERT_EQ(r.len(), 257);
152 ASSERT_EQ(r.pre_len(), 6);
153 for (
int i = 0; i < 257; i++)
155 ASSERT_EQ((
int)(r.data()[i]), i%256);
158 CharVec prev(r.pre_len());
161 for (
size_t i = 0; i < prev.size(); i++)
163 ASSERT_EQ(inv[i], prev[i]);
169 cout <<
"doc before: " << Hex::bin_to_hex(inv) << endl;
170 cout <<
"doc after: " << Hex::bin_to_hex(alld) << endl;
172 ASSERT_EQ(inv, alld);
175 TEST(DerTest, failure)
179 CharVec inv = CharVec({
'\x8a'});
180 ASSERT_THROW(d.
parse(inv), runtime_error);
182 inv = CharVec({
'\x8a',
'\x03',
'\xa1',
'\xa2'});
183 ASSERT_THROW(d.
parse(inv), runtime_error);
185 inv = CharVec({
'\x8a',
'\x82',
'\x01',
'\x01',
'\xab'});
186 ASSERT_THROW(d.
parse(inv), runtime_error);
188 inv = CharVec({
'\x8a',
'\x80'});
189 ASSERT_THROW(d.
parse(inv), runtime_error);
191 inv = CharVec({
'\x8a',
'\x82',
'\x01'});
192 ASSERT_THROW(d.
parse(inv), runtime_error);
195 TEST(DerTest, container_and_integers)
201 '\x8a',
'\x03',
'X',
'Y',
'Z',
202 '\x02',
'\x01',
'\x00',
203 '\x02',
'\x01',
'\x7f',
204 '\x02',
'\x02',
'\x00',
'\x80',
205 '\x02',
'\x02',
'\x01',
'\x00',
206 '\x02',
'\x01',
'\x80',
207 '\x02',
'\x02',
'\xff',
'\x7f',
214 cout <<
"** container dump:" << endl;
217 ASSERT_TRUE(d.root().is_seq());
218 ASSERT_TRUE(d.root().is_contain());
219 ASSERT_FALSE(d.root().is_set());
220 auto& c = d.root().contain();
221 ASSERT_EQ(c.size(), 8);
222 ASSERT_FALSE(c[0]->is_integer());
223 ASSERT_FALSE(c[0]->is_contain());
224 ASSERT_TRUE(c[1]->is_integer());
225 ASSERT_TRUE(c[2]->is_integer());
226 ASSERT_TRUE(c[3]->is_integer());
227 ASSERT_TRUE(c[4]->is_integer());
228 ASSERT_TRUE(c[5]->is_integer());
229 ASSERT_TRUE(c[6]->is_integer());
230 ASSERT_TRUE(c[7]->is_integer());
233 ASSERT_EQ(c[1]->integer(), bn);
235 ASSERT_EQ(c[2]->integer(), bn);
237 ASSERT_EQ(c[3]->integer(), bn);
239 ASSERT_EQ(c[4]->integer(), bn);
242 ASSERT_EQ(c[5]->integer(), bn);
245 ASSERT_EQ(c[6]->integer(), bn);
248 ASSERT_EQ(c[7]->integer(), bn);
253 cout <<
"doc before: " << Hex::bin_to_hex(inv) << endl;
254 cout <<
"doc after: " << Hex::bin_to_hex(alld) << endl;
256 ASSERT_EQ(inv, alld);
264 b->
data() = std::vector<uint8_t>({
'X',
'Y',
'Z'});
265 x->push_back(BasePtr(b));
268 x->push_back(BasePtr(i));
272 x->push_back(BasePtr(i));
276 x->push_back(BasePtr(i));
280 x->push_back(BasePtr(i));
284 x->push_back(BasePtr(i));
288 x->push_back(BasePtr(i));
292 x->push_back(BasePtr(i));
294 cout << endl <<
"contructed doc:\n" << DerDocument::print_element(valptr) << endl;
297 DerDocument::dump_element(valptr, valv);
299 ASSERT_EQ(alld, valv);
302 inv = CharVec({
'\x03',
'\x04',
'\x08',
'\x6e',
'\x5d',
'\xc0'});
303 ASSERT_THROW(d.parse(inv), runtime_error);
306 TEST(DerTest, bit_string)
309 auto inv = CharVec({
'\x03',
'\x04',
'\x06',
'\x6e',
'\x5d',
'\xc0'});
311 auto outv = CharVec({
'\x6e',
'\x5d',
'\xc0'});
316 cout <<
"** bitstring dump:" << endl;
320 ASSERT_TRUE(r.is_bit_string());
321 auto& bs = r.bit_string();
323 ASSERT_EQ(bs.width(), 18);
324 ASSERT_EQ(bs.pad_bits(), 6);
326 ASSERT_FALSE(bs.is_bit_set(0));
327 ASSERT_TRUE(bs.is_bit_set(1));
328 ASSERT_TRUE(bs.is_bit_set(2));
329 ASSERT_FALSE(bs.is_bit_set(3));
330 ASSERT_TRUE(bs.is_bit_set(4));
331 ASSERT_TRUE(bs.is_bit_set(5));
332 ASSERT_TRUE(bs.is_bit_set(6));
333 ASSERT_FALSE(bs.is_bit_set(7));
334 ASSERT_FALSE(bs.is_bit_set(8));
335 ASSERT_TRUE(bs.is_bit_set(9));
336 ASSERT_FALSE(bs.is_bit_set(10));
337 ASSERT_TRUE(bs.is_bit_set(11));
338 ASSERT_TRUE(bs.is_bit_set(12));
339 ASSERT_TRUE(bs.is_bit_set(13));
340 ASSERT_FALSE(bs.is_bit_set(14));
341 ASSERT_TRUE(bs.is_bit_set(15));
342 ASSERT_TRUE(bs.is_bit_set(16));
343 ASSERT_TRUE(bs.is_bit_set(17));
344 ASSERT_FALSE(bs.is_bit_set(18));
345 ASSERT_FALSE(bs.is_bit_set(19));
346 ASSERT_FALSE(bs.is_bit_set(20));
347 ASSERT_FALSE(bs.is_bit_set(21));
348 ASSERT_FALSE(bs.is_bit_set(22));
349 ASSERT_FALSE(bs.is_bit_set(23));
350 ASSERT_FALSE(bs.is_bit_set(24));
355 cout <<
" dump: " << Hex::bin_to_hexstr(dumpvec.data(), dumpvec.size(),
":", 12) << endl;
356 cout <<
" outv: " << Hex::bin_to_hexstr(outv.data(), outv.size(),
":", 12) << endl;
358 ASSERT_EQ(dumpvec, outv);
361 auto newv = CharVec({
'\x6e',
'\x5d',
'\xff'});
372 inv = CharVec({
'\x03',
'\x04',
'\x08',
'\x6e',
'\x5d',
'\xc0'});
373 ASSERT_THROW(d.parse(inv), runtime_error);
376 TEST(DerTest, strings)
382 '\x04',
'\x08',
'o',
'c',
't',
'e',
't',
'[',
'\x00',
']',
383 '\x0c',
'\x04',
'u',
't',
'f',
'8',
384 '\x13',
'\x10',
'p',
'r',
'i',
'n',
't',
'a',
'b',
'l',
'e',
' ',
's',
't',
'r',
'i',
'n',
'g',
385 '\x16',
'\x03',
'i',
'a',
'5',
386 '\x1e',
'\x03',
'b',
'm',
'p'
392 cout <<
"** strings dump:" << endl;
395 ASSERT_TRUE(d.root().is_set());
396 ASSERT_TRUE(d.root().is_contain());
397 ASSERT_FALSE(d.root().is_seq());
398 auto& c = d.root().contain();
399 ASSERT_EQ(c.size(), 5);
401 for (
int i = 0; i < 5; i++)
403 ASSERT_TRUE(c[i]->is_string());
405 ASSERT_TRUE(c[0]->is_octet_string());
406 ASSERT_TRUE(c[1]->is_utf8_string());
407 ASSERT_TRUE(c[2]->is_printable_string());
408 ASSERT_TRUE(c[3]->is_ia5_string());
409 ASSERT_TRUE(c[4]->is_bmp_string());
411 ASSERT_EQ(c[2]->
string(),
string(
"printable string"));
416 cout <<
"doc before: " << Hex::bin_to_hex(inv) << endl;
417 cout <<
"doc after: " << Hex::bin_to_hex(alld) << endl;
419 ASSERT_EQ(inv, alld);
427 s1->set(CharVec({
'o',
'c',
't',
'e',
't',
'[',
'\x00',
']'}));
428 x->push_back(BasePtr(s1));
431 x->push_back(BasePtr(s2));
433 s3->set(
"printable string");
434 x->push_back(BasePtr(s3));
437 x->push_back(BasePtr(s4));
440 x->push_back(BasePtr(s5));
442 cout << endl <<
"contructed doc:\n" << DerDocument::print_element(valptr) << endl;
445 DerDocument::dump_element(valptr, valv);
447 cout <<
"val after: ";
450 if (isprint(c)) cout << c;
451 else cout <<
"<" << std::hex << (int)c << std::dec <<
">";
455 ASSERT_EQ(alld, valv);
458 TEST(DerTest, null_and_bool)
465 '\x01',
'\x01',
'\x00',
466 '\x01',
'\x01',
'\x01'
472 cout <<
"** null and bool dump:" << endl;
475 ASSERT_TRUE(d.root().is_seq());
476 ASSERT_TRUE(d.root().is_contain());
477 ASSERT_FALSE(d.root().is_set());
478 auto& c = d.root().contain();
479 ASSERT_EQ(c.size(), 3);
481 ASSERT_TRUE(c[0]->is_null());
482 ASSERT_TRUE(c[1]->is_boolean());
483 ASSERT_TRUE(c[2]->is_boolean());
484 ASSERT_FALSE(c[1]->
boolean());
485 ASSERT_TRUE(c[2]->
boolean());
490 cout <<
"doc before: " << Hex::bin_to_hex(inv) << endl;
491 cout <<
"doc after: " << Hex::bin_to_hex(alld) << endl;
493 ASSERT_EQ(inv, alld);
500 x->push_back(BasePtr(
new DerNull));
504 x->push_back(BasePtr(b));
508 x->push_back(BasePtr(b));
510 cout << endl <<
"contructed doc:\n" << DerDocument::print_element(valptr) << endl;
513 DerDocument::dump_element(valptr, valv);
515 cout <<
"val after: ";
518 if (isprint(c)) cout << c;
519 else cout <<
"<" << std::hex << (int)c << std::dec <<
">";
523 ASSERT_EQ(alld, valv);
526 struct Timetest :
public testing::Test
529 virtual ~Timetest() {}
532 void verify(
int id,
const string& v,
const string& verify=
"")
536 inv.push_back(v.size());
537 inv.insert(inv.end(), v.begin(), v.end());
540 cout <<
"*** value raw: " << v << endl;
546 ASSERT_EQ(r.
id(),
id);
552 ASSERT_GT(outv.size(), 2);
553 ASSERT_EQ(outv[0], (
char)
id);
554 int sz = (int)outv[1];
555 ASSERT_EQ(outv.size(), sz+2);
557 auto i = outv.begin();
560 ts.insert(ts.begin(), i, outv.end());
561 cout <<
"output ts: " << ts << endl << endl;
565 ASSERT_EQ(ts, verify);
572 time_t make_time(
int year,
int month,
int day,
int hour,
int minute,
int second)
575 memset(&tm, 0,
sizeof(tm));
577 tm.tm_year = year - 1900;
578 tm.tm_mon = month - 1;
590 TEST_F(Timetest, time)
592 ASSERT_THROW(verify(DerBase::type_utc_time,
"030201120102"), runtime_error);
593 ASSERT_THROW(verify(DerBase::type_utc_time,
"030201120102+04"), runtime_error);
594 ASSERT_THROW(verify(DerBase::type_utc_time,
"03020112+04"), runtime_error);
596 verify(DerBase::type_utc_time,
"030201120102Z");
597 verify(DerBase::type_utc_time,
"0302011201Z");
599 verify(DerBase::type_utc_time,
"030201120102+0000",
"030201120102Z");
600 verify(DerBase::type_utc_time,
"0302011201+0000",
"0302011201Z");
602 verify(DerBase::type_utc_time,
"030201120102-0430",
"030201163102Z");
603 verify(DerBase::type_utc_time,
"0302011201-0430",
"0302011631Z");
605 verify(DerBase::type_utc_time,
"030201120102+0430",
"030201073102Z");
606 verify(DerBase::type_utc_time,
"0302011201+0430",
"0302010731Z");
608 ASSERT_THROW(verify(DerBase::type_generalized_time,
"20030201Z"), runtime_error);
610 verify(DerBase::type_generalized_time,
"20030201120102Z");
611 verify(DerBase::type_generalized_time,
"200302011201Z");
612 verify(DerBase::type_generalized_time,
"2003020112Z");
614 verify(DerBase::type_generalized_time,
"20030201120102-0430",
"20030201163102Z");
615 verify(DerBase::type_generalized_time,
"200302011201-0430",
"200302011631Z");
616 verify(DerBase::type_generalized_time,
"2003020112-0430",
"200302011630Z");
618 verify(DerBase::type_generalized_time,
"20030201120102+0430",
"20030201073102Z");
619 verify(DerBase::type_generalized_time,
"200302011201+0430",
"200302010731Z");
620 verify(DerBase::type_generalized_time,
"2003020112+0430",
"200302010730Z");
622 verify(DerBase::type_generalized_time,
"20030201120102-04",
"20030201160102Z");
623 verify(DerBase::type_generalized_time,
"200302011201-04",
"200302011601Z");
624 verify(DerBase::type_generalized_time,
"2003020112-04",
"2003020116Z");
626 verify(DerBase::type_generalized_time,
"20030201120102+04",
"20030201080102Z");
627 verify(DerBase::type_generalized_time,
"200302011201+04",
"200302010801Z");
628 verify(DerBase::type_generalized_time,
"2003020112+04",
"2003020108Z");
630 verify(DerBase::type_generalized_time,
"20030201120102.5Z",
"20030201120102Z");
631 verify(DerBase::type_generalized_time,
"200302011201.5Z",
"20030201120130Z");
632 verify(DerBase::type_generalized_time,
"2003020112.5Z",
"200302011230Z");
635 setenv(
"TZ",
"/usr/share/zoneinfo/America/Los_Angeles", 1);
636 auto t = make_time(2020, 3, 8, 1, 59, 59);
637 verify(DerBase::type_generalized_time,
"20200308015959",
"20200308095959Z");
640 ASSERT_NE(getenv(
"TZ"),
nullptr);
641 ASSERT_EQ(
string(getenv(
"TZ")),
"/usr/share/zoneinfo/America/Los_Angeles");
647 struct Oidtest :
public testing::Test
650 virtual ~Oidtest() {}
655 void parse(CharVec v)
658 inv.push_back(DerBase::type_object_identifier);
659 inv.push_back(v.size());
660 inv.insert(inv.end(), v.begin(), v.end());
663 cout << endl <<
"***\n" << doc << endl;
673 ASSERT_EQ(inv, outv);
675 void validate(std::vector<uint32_t> v)
686 cout << endl <<
"contructed doc:\n" << DerDocument::print_element(valptr) << endl;
689 DerDocument::dump_element(valptr, valv);
690 ASSERT_EQ(inv, valv);
696 parse({
'\x2a',
'\x00',
'\x01',
'\x02'});
697 validate({1,2,0,1,2});
699 parse({
'\x2a',
'\x86',
'\x48',
'\x86',
'\xf7',
'\x0d',
'\x01'});
700 validate({1,2,840,113549,1});
704 using OidVec = std::vector<uint32_t>;
707 ASSERT_THROW(x.
set(OidVec({})), runtime_error);
708 ASSERT_THROW(x.
set(OidVec({1})), runtime_error);
709 ASSERT_THROW(x.
set(OidVec({0,50})), runtime_error);
710 ASSERT_THROW(x.
set(OidVec({3,1})), runtime_error);
time_t time_epoch()
Epoch time.
oid_value object_id()
Return the object identifier value.
bool is_time() const
Is this a time type?
bool uni_class() const
Universal class.
std::vector< uint8_t > & data()
Underlying data.
bool constructed() const
Constructed flag (bit 6).
bool is_object_id() const
Is this an object identifier?
uint32_t id() const
Tag id of the type.
void clear()
Clear the document.
virtual void dump(std::vector< char > &)
Dump and append to a buffer.
virtual void parse(const std::vector< char > &)
Parse a buffer from a binary DER-formatted vector.
DerBase & root()
Root DerBase.
scc::crypto::Bignum & data()
Return the integer (an scc::crypto::Bignum)
void set(const oid_value &v)
Set oid values.
An ASN.1 SEQUENCE or SEQUENCE OF type.
An ASN.1 SET or SET OF type.
PEM formatted DER document.
Distinguished encoding rules (DER).
Common file system utilities.
Binary to hex string converter.
TEST(inet_example, client_server_stream_test)
[Inet client server]