v2 / vlib / x / encoding / asn1 / length_test.v
222 lines · 196 sloc · 7.71 KB · fdc49dc51a0d7e83abd5b383afaaab3f2793f2cf
Raw
1// Copyright (c) 2022, 2023 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 TagAndLengthTest {
7 bytes []u8
8 tag Tag
9 explength i64
10 lastpos int
11 err IError
12}
13
14fn test_tagandlength_handling() ! {
15 // from golang asn.1 test
16 bs := [
17 // Context Specific should be in constructed form
18 TagAndLengthTest{[u8(0x80), 0x01], Tag{.context_specific, false, 0}, 1, 2, none}, // 0b_10_0_00000
19 TagAndLengthTest{[u8(0xa0), 0x01], Tag{.context_specific, true, 0}, 1, 2, none}, // 0b_10_1_00000
20 TagAndLengthTest{[u8(0x02), 0x00], Tag{.universal, false, 2}, 0, 2, none},
21 TagAndLengthTest{[u8(0xfe), 0x00], Tag{.private, true, 30}, 0, 2, none},
22 TagAndLengthTest{[u8(0x1f), 0x1f, 0x00], Tag{.universal, false, 31}, 0, 3, none}, // high tag form
23 TagAndLengthTest{[u8(0x1f), 0x81, 0x00, 0x01], Tag{.universal, false, 128}, 1, 4, none},
24 // the last byte tells its length in long form
25 TagAndLengthTest{[u8(0x1f), 0x81, 0x00, 0x81], Tag{.universal, false, 128}, 1, 4, error('Length: truncated length')},
26 TagAndLengthTest{[u8(0x1f), 0x81, 0x80, 0x01, 0x00], Tag{.universal, false, 16385}, 0, 5, error('Tag number: base 128 integer too large')}, // 1x128^2 + 0x128^1 + 1x128*0
27 TagAndLengthTest{[u8(0x00), 0x81, 0x80], Tag{.universal, false, 0}, 128, 3, none},
28 // need one byte length
29 TagAndLengthTest{[u8(0x00), 0x83, 0x01, 0x00], Tag{.universal, false, 0}, 2, 1, error('Length: truncated length')},
30 // normal version above
31 TagAndLengthTest{[u8(0x00), 0x83, 0x01, 0x01, 0x01], Tag{.universal, false, 0}, 65793, 5, none}, // length = 1x256^2 + 1x256^1 + 1x256^0
32 TagAndLengthTest{[u8(0x1f), 0x85], Tag{.universal, false, 0}, 0, 2, error('Tag: truncated base 128 integer')},
33 TagAndLengthTest{[u8(0x1f), 0x85, 0x81], Tag{.universal, false, 0}, 0, 0, error('Tag: truncated base 128 integer')},
34 // this last bytes tell the length is in undefinite length, 0x80
35 TagAndLengthTest{[u8(0x30), 0x80], Tag{.universal, true, 0x10}, 0, 2, error('Length: unsupported undefinite length')},
36 // still truncated length part
37 TagAndLengthTest{[u8(0x30), 0x81], Tag{.universal, true, 0x10}, 0, 2, error('Length: truncated length')},
38 // still in uneeded form of length
39 TagAndLengthTest{[u8(0x30), 0x81, 0x01], Tag{.universal, true, 0x10}, 1, 3, error('Length: dont needed in long form')},
40 // its fullfill the der requirement
41 TagAndLengthTest{[u8(0x30), 0x81, 0x80], Tag{.universal, true, 0x10}, 128, 3, none},
42 // this tell two bytes of length contains leading spurious zero's
43 TagAndLengthTest{[u8(0xa0), 0x82, 0x00, 0xff], Tag{.context_specific, true, 0}, 255, 1, error('Length: leading zeros')},
44 TagAndLengthTest{[u8(0xa0), 0x82, 0x01, 0xff], Tag{.context_specific, true, 0}, 511, 4, none},
45 // Superfluous zeros in the length should be an error.
46 TagAndLengthTest{[u8(0xa0), 0x82, 0x00, 0xff], Tag{.context_specific, true, 0}, 0, 4, error('Length: leading zeros')}, //{}},
47 // Lengths up to the maximum size of an int should work.
48 TagAndLengthTest{[u8(0xa0), 0x84, 0x7f, 0xff, 0xff, 0xff], Tag{.context_specific, true, 0}, 0x7fffffff, 6, none}, //{2, 0, 0x7fffffff, true}},
49 // Lengths that would overflow an int should be rejected.
50 TagAndLengthTest{[u8(0xa0), 0x84, 0x80, 0x00, 0x00, 0x00], Tag{.context_specific, true, 0}, 2147483648, 6, error('Length: dont needed in long form')}, //{}},
51 // Long length form may not be used for lengths that fit in short form.
52 TagAndLengthTest{[u8(0xa0), 0x81, 0x7f], Tag{.context_specific, true, 0}, 0, 0, error('Length: dont needed in long form')}, //{}},
53 // Tag numbers which would overflow int32 are rejected. (The number below is 2^31.)
54 TagAndLengthTest{[u8(0x1f), 0x88, 0x80, 0x80, 0x80, 0x00, 0x00], Tag{.universal, false, 0}, 0, 0, error('Negative tag number')}, //{}},
55 // Tag numbers that fit in an int32 are valid. (The number below is 2^31 - 1.) but its bigger than max_tag_bytes_length
56 TagAndLengthTest{[u8(0x1f), 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x00], Tag{.universal, false, 2147483647}, 0, 7, error('Tag number: base 128 integer too large')},
57 // Long tag number form may not be used for tags that fit in short form.
58 TagAndLengthTest{[u8(0x1f), 0x1e, 0x00], Tag{.universal, false, 0}, 0, 0, error('Tag: non-minimal tag')}, //{}},
59 ]
60
61 for i, c in bs {
62 // dump(i)
63 tag, pos := Tag.decode(c.bytes) or {
64 assert err == c.err
65 continue
66 }
67 assert tag == c.tag
68 length, idx := Length.decode_from_offset(c.bytes, pos) or {
69 assert err == c.err
70 continue
71 }
72 assert idx == c.lastpos
73 }
74}
75
76struct LengthPackTest {
77 value int
78 expected []u8
79 err IError
80}
81
82fn test_length_pack_and_unpack_tofrom_asn() ! {
83 edata := [
84 LengthPackTest{0, [u8(0x00)], none},
85 LengthPackTest{10, [u8(0x0a)], none},
86 LengthPackTest{127, [u8(0x7f)], none},
87 LengthPackTest{255, [u8(0x81), 0xff], none},
88 LengthPackTest{256, [u8(0x82), 0x01, 0x00], none},
89 LengthPackTest{383, [u8(0x82), 0x01, 127], none},
90 LengthPackTest{257, [u8(0x82), 0x01, 0x01], none},
91 LengthPackTest{65535, [u8(0x82), 0xff, 0xff], none},
92 LengthPackTest{65536, [u8(0x83), 0x01, 0x00, 0x00], none},
93 LengthPackTest{16777215, [u8(0x83), 0xff, 0xff, 0xff], none},
94 ]
95 for i, c in edata {
96 mut dst := []u8{}
97 s := Length.new(c.value)!
98 s.encode(mut dst)!
99 assert dst == c.expected
100
101 length, idx := Length.decode(dst)!
102
103 assert length == c.value
104 assert idx == c.expected.len
105 }
106}
107
108struct ByteLengthTest {
109 value int
110 expected []u8
111}
112
113fn test_basic_simple_length_unpack() {
114 data := [u8(0x82), 0x01, 0x7F]
115 n, pos := Length.decode(data)!
116
117 assert n == 383
118 assert pos == 3
119
120 data2 := [u8(0x82), 0x01, 0x31]
121 n2, pos2 := Length.decode(data2)!
122 assert n2 == 305
123 assert pos2 == 3
124}
125
126fn test_length_pack_and_append() ! {
127 bdata := [
128 ByteLengthTest{1, [u8(1)]},
129 ByteLengthTest{127, [u8(0x7f)]},
130 ByteLengthTest{255, [u8(0xff)]},
131 ByteLengthTest{256, [u8(0x01), 0x00]},
132 ByteLengthTest{383, [u8(0x01), 127]},
133 ByteLengthTest{257, [u8(0x01), 0x01]},
134 ByteLengthTest{7967, [u8(0x1f), 0x1f]},
135 ByteLengthTest{65535, [u8(0xff), 0xff]},
136 ByteLengthTest{65537, [u8(0x01), 0x00, 0x01]},
137 ByteLengthTest{16777215, [u8(0xff), 0xff, 0xff]},
138 ]
139
140 for v in bdata {
141 mut dst := []u8{}
142
143 ln := Length.new(v.value)!
144 ln.to_bytes(mut dst)
145
146 assert dst == v.expected
147 }
148}
149
150struct LengthTest {
151 value int
152 expected int
153}
154
155fn test_length_bytes_len() ! {
156 ldata := [
157 LengthTest{1, 1},
158 LengthTest{128, 1},
159 LengthTest{255, 1},
160 LengthTest{256, 2},
161 LengthTest{383, 2},
162 LengthTest{65535, 2},
163 LengthTest{65536, 3},
164 LengthTest{16777215, 3},
165 LengthTest{16777216, 4},
166 LengthTest{2147483647, 4}, // math.max_i32
167 ]
168
169 for c in ldata {
170 len := Length.new(c.value)!
171 out := len.bytes_len()
172
173 assert out == c.expected
174 }
175}
176
177fn test_calc_length_of_length() ! {
178 data := [
179 LengthTest{1, 1},
180 LengthTest{128, 2},
181 LengthTest{255, 2},
182 LengthTest{256, 3},
183 LengthTest{383, 3},
184 LengthTest{65535, 3},
185 LengthTest{65536, 4},
186 LengthTest{16777215, 4},
187 LengthTest{16777216, 5},
188 LengthTest{2147483647, 5}, // math.max_i32
189 ]
190
191 for c in data {
192 len := Length.new(c.value)!
193 out := len.length_size()!
194
195 assert out == c.expected
196 }
197}
198
199// ASN.1 Test Suite from https://github.com/YuryStrozhevsky/asn1-test-suite
200fn test_tc3_absence_standard_length_block() ! {
201 value := []u8{}
202
203 _, _ := Length.decode(value) or {
204 assert err == error('Length: truncated length')
205 return
206 }
207}
208
209fn test_tc5_unnecessary_usage_long_of_length_form() ! {
210 value := [u8(0x7f), 0xff, 0x7f, 0x81, 0x01, 0x40]
211
212 tag, pos := Tag.decode(value)!
213 // 0x9f == 0b0111_1111
214 assert tag.class == .application
215 assert tag.constructed == true
216 assert pos == 3
217 // the length bytes, [0x81, 0x01] dont needed in long form.
218 _, _ := Length.decode_with_rule(value, pos, .der) or {
219 assert err == error('Length: dont needed in long form')
220 return
221 }
222}
223