v2 / vlib / x / encoding / asn1 / oid_test.v
260 lines · 230 sloc · 7.68 KB · 755ab954b1739345475e1305877836eb1e165245
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 OidWriteTest {
7 inp []int
8 exp []u8
9 err IError
10}
11
12fn assert_no_error(err IError) {
13 assert err.str() == 'none'
14}
15
16fn test_write_oid() ! {
17 dt := [
18 OidWriteTest{[], [], error('ObjectIdentifier: bad oid int array')}, // empty arc
19 OidWriteTest{[0], [u8(0x00)], error('ObjectIdentifier: bad oid int array')}, // only root arc
20 OidWriteTest{[0, 0], [u8(0x00)], none},
21 OidWriteTest{[3, 0], [u8(0x00)], error('ObjectIdentifier: bad oid int array')}, // first arc, 3 is not allowed value
22 OidWriteTest{[0, 40], [u8(0x00)], error('ObjectIdentifier: bad oid int array')}, // second arc, 40 is not allowed (its should <= 39)
23 OidWriteTest{[1, 40], [u8(0x00)], error('ObjectIdentifier: bad oid int array')}, // second arc, 40 is not allowed (its should <= 39)
24 OidWriteTest{[1, 2], [u8(0x2a)], none},
25 OidWriteTest{[2, 5], [u8(0x55)], none},
26 OidWriteTest{[1, 2, 840], [u8(0x2a), 0x86, 0x48], none},
27 OidWriteTest{[1, 2, 840, 113549], [u8(0x2a), 0x86, 0x48, 0x86, 0xF7, 0x0D], none},
28 OidWriteTest{[1, 2, 840, 113549, 1], [u8(0x2a), 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01], none},
29 ]
30
31 for item in dt {
32 oid := ObjectIdentifier.from_ints(item.inp) or {
33 assert err == item.err
34 continue
35 }
36
37 assert_no_error(item.err)
38 dst := oid.payload()!
39
40 assert dst == item.exp
41 }
42}
43
44struct BuildOidTest {
45 inp []int
46 out ObjectIdentifier
47 err IError
48}
49
50fn test_oid_from_ints() ! {
51 td := [
52 BuildOidTest{[1, 2], ObjectIdentifier{
53 value: [1, 2]
54 }, none},
55 BuildOidTest{[1, 2, 3], ObjectIdentifier{
56 value: [1, 2, 3]
57 }, none},
58 BuildOidTest{[1, 4, 4], ObjectIdentifier{
59 value: [1, 4, 4]
60 }, none},
61 BuildOidTest{[1, 39, 6, 256], ObjectIdentifier{
62 value: [1, 39, 6, 256]
63 }, none},
64 // second >= 40 when first < 2 not allowed
65 BuildOidTest{[1, 40, 4], ObjectIdentifier{
66 value: [1, 40, 4]
67 }, error('ObjectIdentifier: bad oid int array')},
68 // first value bigger than 2 was not allowed
69 BuildOidTest{[4, 5, 6], ObjectIdentifier{
70 value: [4, 5, 6]
71 }, error('ObjectIdentifier: bad oid int array')},
72 // second value >= 40 was not allowed when first < 2
73 BuildOidTest{[1, 40, 6], ObjectIdentifier{
74 value: [1, 40, 6]
75 }, error('ObjectIdentifier: bad oid int array')},
76 // when the first arc is 2, the second arc is not limited to 0..39
77 BuildOidTest{[2, 50, 6], ObjectIdentifier{
78 value: [2, 50, 6]
79 }, none},
80 // still valid: value is well below the i32 limit checked by from_ints
81 BuildOidTest{[1, 4, 863123683], ObjectIdentifier{
82 value: [1, 4, 863123683]
83 }, none},
84 BuildOidTest{[4, 0xab, 4], ObjectIdentifier{
85 value: [4, 0xab, 4]
86 }, error('ObjectIdentifier: bad oid int array')},
87 BuildOidTest{[4, 0x0c, 4], ObjectIdentifier{
88 value: [4, 0x0c, 4]
89 }, error('ObjectIdentifier: bad oid int array')},
90 BuildOidTest{[2], ObjectIdentifier{
91 value: [2]
92 }, error('ObjectIdentifier: bad oid int array')},
93 ]
94 for c in td {
95 s := ObjectIdentifier.from_ints(c.inp) or {
96 assert err == c.err
97 continue
98 }
99 assert_no_error(c.err)
100 assert s == c.out
101 }
102}
103
104struct OidStrTest {
105 inp string
106 out ObjectIdentifier
107 err IError
108}
109
110fn test_oid_from_string() ! {
111 td := [
112 OidStrTest{'1.2.840.113549', ObjectIdentifier{
113 value: [1, 2, 840, 113549]
114 }, none},
115 OidStrTest{'1.3.6.1.3', ObjectIdentifier{
116 value: [1, 3, 6, 1, 3]
117 }, none},
118 OidStrTest{'1.2', ObjectIdentifier{
119 value: [1, 2]
120 }, none},
121 OidStrTest{'1.4.4', ObjectIdentifier{
122 value: [1, 4, 4]
123 }, none},
124 OidStrTest{'1.4.x', ObjectIdentifier{
125 value: [1, 4, 4]
126 }, error('common_parse_uint: syntax error x')}, // invalid char
127 OidStrTest{'4.4.4', ObjectIdentifier{
128 value: [4, 4, 4]
129 }, error('ObjectIdentifier: bad oid string')},
130 OidStrTest{'1.4.863123683', ObjectIdentifier{
131 value: [1, 4, 863123683]
132 }, none},
133 OidStrTest{'4.ab.4', ObjectIdentifier{
134 value: [4, 0xab, 4]
135 }, error('common_parse_uint: syntax error ab')}, // invalid char
136 OidStrTest{'4.c.4', ObjectIdentifier{
137 value: [4, 0x0c, 4]
138 }, error('common_parse_uint: syntax error c')}, // invalid char
139 OidStrTest{'2', ObjectIdentifier{
140 value: [2]
141 }, error('ObjectIdentifier: bad string oid length')},
142 ]
143 for s in td {
144 v := ObjectIdentifier.new(s.inp) or {
145 assert err == s.err
146 continue
147 }
148 assert_no_error(s.err)
149 assert v == s.out
150 }
151}
152
153fn test_serialize_oid_basic() {
154 // https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/object-identifier.html
155 inp := [1, 0, 8571, 2, 1]
156 exp := [u8(6), 5, 0x28, 0xC2, 0x7B, 0x02, 0x01]
157 oid := ObjectIdentifier.from_ints(inp)!
158
159 out := encode(oid)!
160
161 assert out == exp
162}
163
164struct OidSerializeTest {
165 inp []int
166 exp []u8
167 err IError
168}
169
170fn test_serialize_decode_oid() {
171 td := [
172 OidSerializeTest{[0, 0], [u8(0x06), 0x01, 0x00], none},
173 OidSerializeTest{[1, 2, 3], [u8(0x06), 0x02, 0x2a, 0x03], none},
174 OidSerializeTest{[1, 3, 6, 1, 3], [u8(0x06), 0x04, 0x2b, 0x06, 1, 3], none},
175 OidSerializeTest{[2, 999, 1234], [u8(0x06), 0x04, 0x88, 0x37, 0x89, 0x52], none},
176 OidSerializeTest{[2, 999, 3], [u8(0x06), 0x03, 0x88, 0x37, 0x03], none}, // Example of ITU-T X.690
177 // from https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier
178 OidSerializeTest{[1, 3, 6, 1, 4, 1, 311, 21, 20], [u8(0x06), 0x09, 0x2b, 0x06, 0x01, 0x04,
179 0x01, 0x82, 0x37, 0x15, 0x14], none},
180 // from rust-asn1 test data
181 OidSerializeTest{[1, 2, 840, 113549], [u8(0x06), 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d], none},
182 OidSerializeTest{[1, 2, 3, 4], [u8(0x06), 0x03, 0x2a, 0x03, 0x04], none},
183 OidSerializeTest{[1, 2, 840, 133549, 1, 1, 5], [u8(0x06), 0x09, 0x2a, 0x86, 0x48, 0x88,
184 0x93, 0x2d, 0x01, 0x01, 0x05], none},
185 OidSerializeTest{[2, 100, 3], [u8(0x06), 0x03, 0x81, 0x34, 0x03], none},
186 OidSerializeTest{[1, 100, 3], [u8(0x06), 0x03, 0x81, 0x34, 0x03], error('ObjectIdentifier: bad oid int array')},
187 OidSerializeTest{[4, 100, 3], [u8(0x06), 0x03, 0x81, 0x34, 0x03], error('ObjectIdentifier: bad oid int array')},
188 ]
189 for t in td {
190 // dump(t.inp)
191 oid := ObjectIdentifier.from_ints(t.inp) or {
192 assert err == t.err
193 continue
194 }
195 out := encode(oid) or {
196 assert err == t.err
197 continue
198 }
199
200 assert_no_error(t.err)
201 assert out == t.exp
202 // dump(out)
203 // decode back
204 oidback, next := ObjectIdentifier.decode(out)!
205
206 assert oidback.tag().tag_number() == int(TagType.oid)
207 assert oidback == oid
208 }
209}
210
211fn test_oid_encode_decode() ! {
212 inp := '1.2.840.113549'
213
214 src := ObjectIdentifier.new(inp)!
215
216 out := encode(src)!
217 exp := [u8(0x06), 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d]
218
219 assert out == exp
220
221 oidback, _ := ObjectIdentifier.decode(out)!
222
223 assert oidback.str() == '${inp}'
224 assert oidback.tag().tag_number() == 6
225}
226
227fn test_tc21_long_format_of_oid_encoding_should_error_in_der() ! {
228 data := [u8(0x06), 0x06, 0x80, 0x80, 0x51, 0x80, 0x80, 0x01]
229
230 _, _ := ObjectIdentifier.decode(data) or {
231 assert err == error('integer is not minimaly encoded')
232 return
233 }
234}
235
236fn test_tc22_too_big_value_oid() ! {
237 data := [u8(0x06), 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
238 0x85, 0x03, 0x02, 0x02, 0x03]
239
240 _, _ := ObjectIdentifier.decode(data) or {
241 assert err == error('integer is not minimaly encoded')
242 return
243 }
244}
245
246// Taken from https://letsencrypt.org/id/docs/a-warm-welcome-to-asn1-and-der/
247//
248// OID 1.2.840.113549.1.1.11 (representing sha256WithRSAEncryption) is encoded like so:
249// 06 09 2a 86 48 86 f7 0d 01 01 0b
250fn test_sha256withrsaencryption_oid() ! {
251 oid := ObjectIdentifier.new('1.2.840.113549.1.1.11')!
252 expected := [u8(0x06), 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b]
253
254 out := encode(oid)!
255 assert out == expected
256
257 // decode back
258 ob, _ := ObjectIdentifier.decode(out)!
259 assert ob.equal(oid)
260}
261