1
2
3
4
5 package x509
6
7 import (
8 "encoding"
9 "encoding/asn1"
10 "math"
11 "testing"
12 )
13
14 var oidTests = []struct {
15 raw []byte
16 valid bool
17 str string
18 ints []uint64
19 }{
20 {[]byte{}, false, "", nil},
21 {[]byte{0x80, 0x01}, false, "", nil},
22 {[]byte{0x01, 0x80, 0x01}, false, "", nil},
23
24 {[]byte{1, 2, 3}, true, "0.1.2.3", []uint64{0, 1, 2, 3}},
25 {[]byte{41, 2, 3}, true, "1.1.2.3", []uint64{1, 1, 2, 3}},
26 {[]byte{86, 2, 3}, true, "2.6.2.3", []uint64{2, 6, 2, 3}},
27
28 {[]byte{41, 255, 255, 255, 127}, true, "1.1.268435455", []uint64{1, 1, 268435455}},
29 {[]byte{41, 0x87, 255, 255, 255, 127}, true, "1.1.2147483647", []uint64{1, 1, 2147483647}},
30 {[]byte{41, 255, 255, 255, 255, 127}, true, "1.1.34359738367", []uint64{1, 1, 34359738367}},
31 {[]byte{42, 255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "1.2.9223372036854775807", []uint64{1, 2, 9223372036854775807}},
32 {[]byte{43, 0x81, 255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "1.3.18446744073709551615", []uint64{1, 3, 18446744073709551615}},
33 {[]byte{44, 0x83, 255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "1.4.36893488147419103231", nil},
34 {[]byte{85, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "2.5.1180591620717411303423", nil},
35 {[]byte{85, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "2.5.19342813113834066795298815", nil},
36
37 {[]byte{255, 255, 255, 127}, true, "2.268435375", []uint64{2, 268435375}},
38 {[]byte{0x87, 255, 255, 255, 127}, true, "2.2147483567", []uint64{2, 2147483567}},
39 {[]byte{255, 127}, true, "2.16303", []uint64{2, 16303}},
40 {[]byte{255, 255, 255, 255, 127}, true, "2.34359738287", []uint64{2, 34359738287}},
41 {[]byte{255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "2.9223372036854775727", []uint64{2, 9223372036854775727}},
42 {[]byte{0x81, 255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "2.18446744073709551535", []uint64{2, 18446744073709551535}},
43 {[]byte{0x83, 255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "2.36893488147419103151", nil},
44 {[]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "2.1180591620717411303343", nil},
45 {[]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127}, true, "2.19342813113834066795298735", nil},
46
47 {[]byte{41, 0x80 | 66, 0x80 | 44, 0x80 | 11, 33}, true, "1.1.139134369", []uint64{1, 1, 139134369}},
48 {[]byte{0x80 | 66, 0x80 | 44, 0x80 | 11, 33}, true, "2.139134289", []uint64{2, 139134289}},
49 }
50
51 func TestOID(t *testing.T) {
52 for _, v := range oidTests {
53 oid, ok := newOIDFromDER(v.raw)
54 if ok != v.valid {
55 t.Errorf("newOIDFromDER(%v) = (%v, %v); want = (OID, %v)", v.raw, oid, ok, v.valid)
56 continue
57 }
58
59 if !ok {
60 continue
61 }
62
63 if str := oid.String(); str != v.str {
64 t.Errorf("(%#v).String() = %v, want; %v", oid, str, v.str)
65 }
66
67 var asn1OID asn1.ObjectIdentifier
68 for _, v := range v.ints {
69 if v > math.MaxInt32 {
70 asn1OID = nil
71 break
72 }
73 asn1OID = append(asn1OID, int(v))
74 }
75
76 o, ok := oid.toASN1OID()
77 if shouldOk := asn1OID != nil; shouldOk != ok {
78 t.Errorf("(%#v).toASN1OID() = (%v, %v); want = (%v, %v)", oid, o, ok, asn1OID, shouldOk)
79 continue
80 }
81
82 if asn1OID != nil && !o.Equal(asn1OID) {
83 t.Errorf("(%#v).toASN1OID() = (%v, true); want = (%v, true)", oid, o, asn1OID)
84 }
85
86 if v.ints != nil {
87 oid2, err := OIDFromInts(v.ints)
88 if err != nil {
89 t.Errorf("OIDFromInts(%v) = (%v, %v); want = (%v, nil)", v.ints, oid2, err, oid)
90 }
91 if !oid2.Equal(oid) {
92 t.Errorf("OIDFromInts(%v) = (%v, nil); want = (%v, nil)", v.ints, oid2, oid)
93 }
94 }
95 }
96 }
97
98 func TestInvalidOID(t *testing.T) {
99 cases := []struct {
100 str string
101 ints []uint64
102 }{
103 {str: "", ints: []uint64{}},
104 {str: "1", ints: []uint64{1}},
105 {str: "3", ints: []uint64{3}},
106 {str: "3.100.200", ints: []uint64{3, 100, 200}},
107 {str: "1.81", ints: []uint64{1, 81}},
108 {str: "1.81.200", ints: []uint64{1, 81, 200}},
109 }
110
111 for _, tt := range cases {
112 oid, err := OIDFromInts(tt.ints)
113 if err == nil {
114 t.Errorf("OIDFromInts(%v) = (%v, %v); want = (OID{}, %v)", tt.ints, oid, err, errInvalidOID)
115 }
116
117 oid2, err := ParseOID(tt.str)
118 if err == nil {
119 t.Errorf("ParseOID(%v) = (%v, %v); want = (OID{}, %v)", tt.str, oid2, err, errInvalidOID)
120 }
121
122 var oid3 OID
123 err = oid3.UnmarshalText([]byte(tt.str))
124 if err == nil {
125 t.Errorf("(*OID).UnmarshalText(%v) = (%v, %v); want = (OID{}, %v)", tt.str, oid3, err, errInvalidOID)
126 }
127 }
128 }
129
130 func TestOIDEqual(t *testing.T) {
131 var cases = []struct {
132 oid OID
133 oid2 OID
134 eq bool
135 }{
136 {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: mustNewOIDFromInts(t, []uint64{1, 2, 3}), eq: true},
137 {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: mustNewOIDFromInts(t, []uint64{1, 2, 4}), eq: false},
138 {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: mustNewOIDFromInts(t, []uint64{1, 2, 3, 4}), eq: false},
139 {oid: mustNewOIDFromInts(t, []uint64{2, 33, 22}), oid2: mustNewOIDFromInts(t, []uint64{2, 33, 23}), eq: false},
140 {oid: OID{}, oid2: OID{}, eq: true},
141 {oid: OID{}, oid2: mustNewOIDFromInts(t, []uint64{2, 33, 23}), eq: false},
142 }
143
144 for _, tt := range cases {
145 if eq := tt.oid.Equal(tt.oid2); eq != tt.eq {
146 t.Errorf("(%v).Equal(%v) = %v, want %v", tt.oid, tt.oid2, eq, tt.eq)
147 }
148 }
149 }
150
151 var (
152 _ encoding.BinaryMarshaler = OID{}
153 _ encoding.BinaryUnmarshaler = new(OID)
154 _ encoding.TextMarshaler = OID{}
155 _ encoding.TextUnmarshaler = new(OID)
156 )
157
158 func TestOIDMarshal(t *testing.T) {
159 cases := []struct {
160 in string
161 out OID
162 err error
163 }{
164 {in: "", err: errInvalidOID},
165 {in: "0", err: errInvalidOID},
166 {in: "1", err: errInvalidOID},
167 {in: ".1", err: errInvalidOID},
168 {in: ".1.", err: errInvalidOID},
169 {in: "1.", err: errInvalidOID},
170 {in: "1..", err: errInvalidOID},
171 {in: "1.2.", err: errInvalidOID},
172 {in: "1.2.333.", err: errInvalidOID},
173 {in: "1.2.333..", err: errInvalidOID},
174 {in: "1.2..", err: errInvalidOID},
175 {in: "+1.2", err: errInvalidOID},
176 {in: "-1.2", err: errInvalidOID},
177 {in: "1.-2", err: errInvalidOID},
178 {in: "1.2.+333", err: errInvalidOID},
179 }
180
181 for _, v := range oidTests {
182 oid, ok := newOIDFromDER(v.raw)
183 if !ok {
184 continue
185 }
186 cases = append(cases, struct {
187 in string
188 out OID
189 err error
190 }{
191 in: v.str,
192 out: oid,
193 err: nil,
194 })
195 }
196
197 for _, tt := range cases {
198 o, err := ParseOID(tt.in)
199 if err != tt.err {
200 t.Errorf("ParseOID(%q) = %v; want = %v", tt.in, err, tt.err)
201 continue
202 }
203
204 var o2 OID
205 err = o2.UnmarshalText([]byte(tt.in))
206 if err != tt.err {
207 t.Errorf("(*OID).UnmarshalText(%q) = %v; want = %v", tt.in, err, tt.err)
208 continue
209 }
210
211 if err != nil {
212 continue
213 }
214
215 if !o.Equal(tt.out) {
216 t.Errorf("(*OID).UnmarshalText(%q) = %v; want = %v", tt.in, o, tt.out)
217 continue
218 }
219
220 if !o2.Equal(tt.out) {
221 t.Errorf("ParseOID(%q) = %v; want = %v", tt.in, o2, tt.out)
222 continue
223 }
224
225 marshalled, err := o.MarshalText()
226 if string(marshalled) != tt.in || err != nil {
227 t.Errorf("(%#v).MarshalText() = (%v, %v); want = (%v, nil)", o, string(marshalled), err, tt.in)
228 continue
229 }
230
231 binary, err := o.MarshalBinary()
232 if err != nil {
233 t.Errorf("(%#v).MarshalBinary() = %v; want = nil", o, err)
234 }
235
236 var o3 OID
237 if err := o3.UnmarshalBinary(binary); err != nil {
238 t.Errorf("(*OID).UnmarshalBinary(%v) = %v; want = nil", binary, err)
239 }
240
241 if !o3.Equal(tt.out) {
242 t.Errorf("(*OID).UnmarshalBinary(%v) = %v; want = %v", binary, o3, tt.out)
243 continue
244 }
245 }
246 }
247
248 func TestOIDEqualASN1OID(t *testing.T) {
249 maxInt32PlusOne := int64(math.MaxInt32) + 1
250 var cases = []struct {
251 oid OID
252 oid2 asn1.ObjectIdentifier
253 eq bool
254 }{
255 {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3}, eq: true},
256 {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 4}, eq: false},
257 {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3, 4}, eq: false},
258 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 22}), oid2: asn1.ObjectIdentifier{1, 33, 23}, eq: false},
259 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 23}), oid2: asn1.ObjectIdentifier{1, 33, 22}, eq: false},
260 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 127}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: true},
261 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: false},
262 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: true},
263 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: true},
264 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: false},
265 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: false},
266 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 255}), oid2: asn1.ObjectIdentifier{1, 33, 255}, eq: true},
267 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{1, 33, 256}, eq: true},
268 {oid: mustNewOIDFromInts(t, []uint64{2, 33, 257}), oid2: asn1.ObjectIdentifier{2, 33, 256}, eq: false},
269 {oid: mustNewOIDFromInts(t, []uint64{2, 33, 256}), oid2: asn1.ObjectIdentifier{2, 33, 257}, eq: false},
270
271 {oid: mustNewOIDFromInts(t, []uint64{1, 33}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: false},
272 {oid: mustNewOIDFromInts(t, []uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33}, eq: false},
273 {oid: mustNewOIDFromInts(t, []uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: true},
274 {
275 oid: mustNewOIDFromInts(t, []uint64{1, 33, math.MaxInt32 + 1}),
276 oid2: asn1.ObjectIdentifier{1, 33 , int(maxInt32PlusOne)},
277 eq: false,
278 },
279
280 {oid: mustNewOIDFromInts(t, []uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{}, eq: false},
281 {oid: OID{}, oid2: asn1.ObjectIdentifier{1, 33, 256}, eq: false},
282 {oid: OID{}, oid2: asn1.ObjectIdentifier{}, eq: false},
283 }
284
285 for _, tt := range cases {
286 if eq := tt.oid.EqualASN1OID(tt.oid2); eq != tt.eq {
287 t.Errorf("(%v).EqualASN1OID(%v) = %v, want %v", tt.oid, tt.oid2, eq, tt.eq)
288 }
289 }
290 }
291
292 func TestOIDUnmarshalBinary(t *testing.T) {
293 for _, tt := range oidTests {
294 var o OID
295 err := o.UnmarshalBinary(tt.raw)
296
297 expectErr := errInvalidOID
298 if tt.valid {
299 expectErr = nil
300 }
301
302 if err != expectErr {
303 t.Errorf("(o *OID).UnmarshalBinary(%v) = %v; want = %v; (o = %v)", tt.raw, err, expectErr, o)
304 }
305 }
306 }
307
308 func BenchmarkOIDMarshalUnmarshalText(b *testing.B) {
309 oid := mustNewOIDFromInts(b, []uint64{1, 2, 3, 9999, 1024})
310 for range b.N {
311 text, err := oid.MarshalText()
312 if err != nil {
313 b.Fatal(err)
314 }
315 var o OID
316 if err := o.UnmarshalText(text); err != nil {
317 b.Fatal(err)
318 }
319 }
320 }
321
322 func mustNewOIDFromInts(t testing.TB, ints []uint64) OID {
323 oid, err := OIDFromInts(ints)
324 if err != nil {
325 t.Fatalf("OIDFromInts(%v) unexpected error: %v", ints, err)
326 }
327 return oid
328 }
329
View as plain text