v2 / vlib / x / encoding / asn1 / core_test.v
162 lines · 151 sloc · 6.25 KB · fdc49dc51a0d7e83abd5b383afaaab3f2793f2cf
Raw
1// Copyright (c) 2022, 2024 blackshirt. All rights reserved.
2// Use of this source code is governed by a MIT License
3// that can be found in the LICENSE file.
4module asn1
5
6struct TagCreation {
7 class TagClass
8 constructed bool
9 number int
10 err IError
11}
12
13fn test_tag_new_constructor() {
14 tags := [
15 TagCreation{.universal, false, 1, none},
16 TagCreation{.universal, true, 1, none},
17 // sequence should be constructed set
18 TagCreation{.universal, true, 16, none},
19 TagCreation{.universal, false, 16, error('For SEQUENCE(OF) or SET(OF) type, should be in constructed form')},
20 // set
21 TagCreation{.universal, true, 17, none},
22 TagCreation{.universal, false, 17, error('For SEQUENCE(OF) or SET(OF) type, should be in constructed form')},
23 //
24 TagCreation{.universal, false, 28, none},
25 TagCreation{.universal, false, 0x1f, none}, // 31
26 TagCreation{.universal, false, 0x7f, none},
27 TagCreation{.universal, false, 255, none}, // 0xff
28 TagCreation{.universal, true, 255, none}, // 0xff
29 TagCreation{.universal, true, 16380, error('Not a valid tag number for universal class=16380')},
30 // Context Specific should be in constructed form
31 TagCreation{.context_specific, true, 128, none}, // 0x80
32 TagCreation{.context_specific, false, 128, error('Context Specific should be in constructed form')}, // 0x80
33 // Others was as is
34 TagCreation{.private, false, 256, none},
35 TagCreation{.private, true, 16383, none},
36 TagCreation{.private, true, 16500, error('Unallowed tag number, 16500 exceed limit')},
37 TagCreation{.application, false, 16000, none},
38 TagCreation{.application, false, 16384, error('Unallowed tag number, 16384 exceed limit')},
39 TagCreation{.application, true, 65535, error('Unallowed tag number, 65535 exceed limit')},
40 ]
41 for i, c in tags {
42 // creates tag with constructed bit set
43 t := Tag.new(c.class, c.constructed, c.number) or {
44 assert err == c.err
45 continue
46 }
47 assert t.tag_class() == c.class
48 assert t.is_constructed() == c.constructed
49 assert t.tag_number() == c.number
50 }
51}
52
53struct TagLengthTest {
54 class TagClass
55 number int
56 explength int
57 err IError
58}
59
60fn test_class_tag_length_handling() ! {
61 tags := [
62 TagLengthTest{.universal, 0, 1, none},
63 TagLengthTest{.universal, 1, 1, none},
64 TagLengthTest{.universal, 28, 1, none},
65 TagLengthTest{.universal, 0x1f, 2, none}, // 31
66 TagLengthTest{.universal, 0x7f, 2, none},
67 TagLengthTest{.context_specific, 128, 3, none}, // 0x80
68 TagLengthTest{.universal, 255, 3, none}, // 0xff
69 TagLengthTest{.private, 256, 3, error('Not a valid tag number for universal class=256')},
70 TagLengthTest{.universal, 16380, 3, error('Not a valid tag number for universal class=16380')},
71 TagLengthTest{.private, 16383, 3, none},
72 TagLengthTest{.application, 16384, 4, error('Unallowed tag number, 16384 exceed limit')},
73 TagLengthTest{.application, 65535, 4, error('Unallowed tag number, 65535 exceed limit')},
74 ]
75
76 for i, c in tags {
77 // creates tag with constructed bit set
78 t := Tag.new(c.class, true, c.number) or {
79 assert err == c.err
80 continue
81 }
82 n := t.tag_size()
83 assert n == c.explength
84 }
85}
86
87struct TagDecodeTest {
88 bytes []u8
89 class TagClass
90 constructed bool
91 number int
92 lastpos int
93 err IError
94}
95
96fn test_tag_decode() ! {
97 data := [
98 // 0b1000_000 telss its class is .context_specific, but constructed bit was not set
99 TagDecodeTest{[u8(0x80), 0x01], .context_specific, false, 0, 1, none},
100 TagDecodeTest{[u8(0xa0), 0x01], .context_specific, true, 0, 1, none}, //{2, 0, 1, true}},
101 TagDecodeTest{[u8(0x02), 0x00], .universal, false, 2, 1, none},
102 TagDecodeTest{[u8(0xfe), 0x00], .private, true, 30, 1, none},
103 TagDecodeTest{[u8(0x1f), 0x1f, 0x00], .universal, false, 31, 2, none}, // high tag form
104 TagDecodeTest{[u8(0x1f), 0x81, 0x00, 0x00], .universal, false, 128, 3, none},
105 TagDecodeTest{[u8(0x1f), 0x81, 0x80, 0x01, 0x00], .universal, false, 16385, 4, error('Tag number: base 128 integer too large')}, // 1x128^2 + 0x128^1 + 1x128*0
106 TagDecodeTest{[u8(0x00), 0x81, 0x80], .universal, false, 0, 1, none},
107 TagDecodeTest{[u8(0x00), 0x83, 0x01, 0x00], .universal, false, 0, 1, none},
108 TagDecodeTest{[u8(0x1f), 0x85], .universal, false, 0, 1, error('Tag: truncated base 128 integer')},
109 TagDecodeTest{[u8(0x1f), 0x85, 0x81], .universal, false, 0, 0, error('Tag: truncated base 128 integer')},
110 TagDecodeTest{[u8(0x30), 0x80], .universal, true, 0x10, 1, none},
111 TagDecodeTest{[u8(0xa0), 0x82, 0x00, 0xff], .context_specific, true, 0, 1, none},
112 ]
113
114 for i, c in data {
115 // dump(i)
116 tag, pos := Tag.decode(c.bytes) or {
117 assert err == c.err
118 continue
119 }
120 assert tag.class == c.class
121 assert tag.constructed == c.constructed
122 assert tag.number == c.number
123 assert pos == c.lastpos
124 }
125}
126
127struct TagNumberTest {
128 num int
129 class TagClass
130 constructed bool
131 exp []u8
132 err IError
133}
134
135fn test_serialize_tag() ! {
136 data := [
137 TagNumberTest{0, .universal, false, [u8(0x00)], none},
138 TagNumberTest{32, .universal, false, [u8(0x1f), 0x20], none}, // multibyte tag: 0x1f 0x20
139 TagNumberTest{255, .universal, false, [u8(0x1f), 0x81, 0x7f], none}, // multibyte tag: 0x1f 0x81 0x7f
140 TagNumberTest{0, .universal, true, [u8(0x20)], none}, // bits 6 set, 0010 0000 == 32
141 TagNumberTest{1, .universal, true, [u8(0x21)], none}, // bits 6 set, 0010 0001 == 31
142 TagNumberTest{32, .universal, true, [u8(0x3f), 0x20], none}, // multibyte tag: 00111111 0x20
143 TagNumberTest{32, .application, true, [u8(0x7f), 0x20], none}, // multibyte tag: 127 (01111111) 0x20
144 TagNumberTest{32, .context_specific, true, [u8(0xbf), 0x20], none}, // multibyte tag: 197 (10111111) 0x20
145 TagNumberTest{32, .private, true, [u8(0xff), 0x20], none}, // multibyte tag: 255 (11111111) 0x20
146 TagNumberTest{255, .context_specific, true, [u8(0xbf), 0x81, 0x7f], none}, // multibyte tag: 0xbf 0x81 0x7f
147 // private class 0xdf = 0b1101_1111
148 TagNumberTest{16383, .private, false, [u8(0xdf), 0xff, 0x7f], none}, // multibyte tag: 0x1f 0xff 0x7f
149 // overflow max_tag_value
150 TagNumberTest{16385, .context_specific, true, [u8(0x1f), 0xff, 0x7f], error('Unallowed tag number, 16385 exceed limit')}, // multibyte tag: 0x1f 0xff 0x7f
151 ]
152
153 for i, c in data {
154 mut dst := []u8{}
155 tag := Tag.new(c.class, c.constructed, c.num) or {
156 assert err == c.err
157 continue
158 }
159 tag.encode(mut dst)!
160 assert dst == c.exp
161 }
162}
163