This repository has been archived by the owner on Mar 13, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 28
/
decode.go
538 lines (487 loc) · 14.3 KB
/
decode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
package asn1
import (
"bytes"
"io"
"reflect"
"sort"
)
// Expected values
type expectedElement struct {
class uint
tag uint
decoder decoderFunction
}
// Expected values for fields
type expectedFieldElement struct {
expectedElement
value reflect.Value
opts *fieldOptions
}
// Decode parses the given data into obj. The argument obj should be a reference
// to the value that will hold the parsed data.
//
// See (*Context).DecodeWithOptions() for further details.
//
func (ctx *Context) Decode(data []byte, obj interface{}) (rest []byte, err error) {
return ctx.DecodeWithOptions(data, obj, "")
}
// DecodeWithOptions parses the given data into obj using the additional
// options. The argument obj should be a reference to the value that will hold
// the parsed data.
//
// It uses the reflect package to inspect obj and because of that only exported
// struct fields (those that start with a capital letter) are considered.
//
// The Context object defines the decoding rules (BER or DER) and the types
// available for CHOICE types.
//
// The asn1 package maps Go types to ASN.1 data structures. The package also
// provides types to specific ASN.1 data structures. The default mapping is
// shown in the table below:
//
// Go type | ASN.1 universal tag
// -----------------------|--------------------
// bool | BOOLEAN
// All int and uint types | INTEGER
// *big.Int | INTEGER
// string | OCTET STRING
// []byte | OCTET STRING
// asn1.Oid | OBJECT INDETIFIER
// asn1.Null | NULL
// Any array or slice | SEQUENCE OF
// Any struct | SEQUENCE
//
// Arrays and slices are decoded using different rules. A slice is always
// appended while an array requires an exact number of elements, otherwise a
// ParseError is returned.
//
// The default mapping can be changed using options provided in the argument
// options (for the root value) or via struct tags for struct fields. Struct
// tags use the namei space "asn1".
//
// The available options for encoding and decoding are:
//
// tag
//
// This option requires an numeric argument (ie: "tag:1") and indicates that a
// element is encoded and decoded as a context specific element with the given
// tag number. The context specific class can be overridden with the options
// "application" or "universal".
//
// universal
//
// Sets the tag class to universal. Requires "tag".
//
// application
//
// Sets the tag class to application. Requires "tag".
//
// explicit
//
// Indicates the element is encoded with an enclosing tag. It's usually
// used in conjunction with "tag".
//
// optional
//
// Indicates that an element can be suppressed.
//
// A missing element that is not marked with "optional" or "default" causes a
// ParseError to be returned during decoding. A missing element marked as
// optional is left untouched.
//
// During encoding, a zero value elements is suppressed from output if it's
// marked as optional.
//
// default
//
// This option is handled similarly to the "optional" option but requires a
// numeric argument (ie: "default:1").
//
// A missing element that is marked with "default" is set to the given default
// value during decoding.
//
// A zero value marked with "default" is suppressed from output when encoding
// is set to DER or is encoded with the given default value when encoding is set
// to BER.
//
// indefinite
//
// This option is used only during encoding and causes a constructed element to
// be encoded using the indefinite form.
//
// choice
//
// Indicates that an element can be of one of several types as defined by
// (*Context).AddChoice()
//
// set
//
// Indicates that a struct, array or slice should be encoded and decoded as a
// SET instead of a SEQUENCE.
//
// It also affects the way that structs are encoded and decoded in DER. A struct
// marked with "set" has its fields always encoded in the ascending order of its
// tags, instead of following the order that the fields are defined in the
// struct.
//
// Similarly, a struct marked with "set" always enforces that same order when
// decoding in DER.
//
func (ctx *Context) DecodeWithOptions(data []byte, obj interface{}, options string) (rest []byte, err error) {
opts, err := parseOptions(options)
if err != nil {
return nil, err
}
value := reflect.ValueOf(obj)
switch value.Kind() {
case reflect.Ptr, reflect.Interface:
value = value.Elem()
}
if !value.CanSet() {
return nil, syntaxError("go type '%s' is read-only", value.Type())
}
reader := bytes.NewBuffer(data)
err = ctx.decode(reader, value, opts)
if err != nil {
return nil, err
}
return reader.Bytes(), nil
}
// Main decode function
func (ctx *Context) decode(reader io.Reader, value reflect.Value, opts *fieldOptions) error {
// Parse an Asn.1 element
raw, err := decodeRawValue(reader)
if err != nil {
return err
}
if ctx.der.decoding && raw.Indefinite {
return parseError("indefinite length form is not supported by DER mode")
}
elem, err := ctx.getExpectedElement(raw, value.Type(), opts)
if err != nil {
return err
}
// And tag must match
if raw.Class != elem.class || raw.Tag != elem.tag {
ctx.log.Printf("%#v\n", opts)
return parseError("expected tag (%d,%d) but found (%d,%d)",
elem.class, elem.tag, raw.Class, raw.Tag)
}
return elem.decoder(raw.Content, value)
}
// getExpectedElement returns the expected element for a given type. raw is only
// used as hint when decoding choices.
// TODO: consider replacing raw for class and tag number.
func (ctx *Context) getExpectedElement(raw *rawValue, elemType reflect.Type, opts *fieldOptions) (elem expectedElement, err error) {
// Get the expected universal tag and its decoder for the given Go type
elem, err = ctx.getUniversalTag(elemType, opts)
if err != nil {
return
}
// Modify the expected tag and decoder function based on the given options
if opts.tag != nil {
elem.class = classContextSpecific
elem.tag = uint(*opts.tag)
}
if opts.universal {
elem.class = classUniversal
}
if opts.application {
elem.class = classApplication
}
if opts.explicit {
elem.decoder = func(data []byte, value reflect.Value) error {
// Unset previous flags
opts.explicit = false
opts.tag = nil
opts.application = false
// Parse child
reader := bytes.NewBuffer(data)
return ctx.decode(reader, value, opts)
}
return
}
if opts.choice != nil {
// Get the registered choices
var entry choiceEntry
entry, err = ctx.getChoiceByTag(*opts.choice, raw.Class, raw.Tag)
if err != nil {
return
}
// Get the decoder for the new value
elem.class, elem.tag = raw.Class, raw.Tag
elem.decoder = func(data []byte, value reflect.Value) error {
// Allocate a new value and set to the current one
nestedValue := reflect.New(entry.typ).Elem()
err = entry.decoder(data, nestedValue)
if err != nil {
return err
}
value.Set(nestedValue)
return nil
}
}
// At this point a decoder function already be found
if elem.decoder == nil {
err = parseError("go type not supported '%s'", elemType)
}
return
}
// getUniversalTag maps an type to a Asn.1 universal type.
func (ctx *Context) getUniversalTag(objType reflect.Type, opts *fieldOptions) (elem expectedElement, err error) {
elem.class = classUniversal
// Special types:
switch objType {
case bigIntType:
elem.tag = tagInteger
elem.decoder = ctx.decodeBigInt
case oidType:
elem.tag = tagOid
elem.decoder = ctx.decodeOid
case nullType:
elem.tag = tagNull
elem.decoder = ctx.decodeNull
default:
// Generic types:
elem = ctx.getUniversalTagByKind(objType, opts)
}
// Check options for universal types
if opts.set {
if elem.tag != tagSequence {
err = syntaxError(
"'set' cannot be used with Go type '%s'", objType)
}
elem.tag = tagSet
}
return
}
// getUniversalTagByKind uses type kind to defined the decoder.
func (ctx *Context) getUniversalTagByKind(objType reflect.Type, opts *fieldOptions) (elem expectedElement) {
switch objType.Kind() {
case reflect.Bool:
elem.tag = tagBoolean
elem.decoder = ctx.decodeBool
case reflect.String:
elem.tag = tagOctetString
elem.decoder = ctx.decodeString
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
elem.tag = tagInteger
elem.decoder = ctx.decodeInt
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
elem.tag = tagInteger
elem.decoder = ctx.decodeUint
case reflect.Struct:
elem.tag = tagSequence
elem.decoder = ctx.decodeStruct
if opts.set {
elem.decoder = ctx.decodeStructAsSet
}
case reflect.Array:
if objType.Elem().Kind() == reflect.Uint8 {
elem.tag = tagOctetString
elem.decoder = ctx.decodeOctetString
} else {
elem.tag = tagSequence
elem.decoder = ctx.decodeArray
}
case reflect.Slice:
if objType.Elem().Kind() == reflect.Uint8 {
elem.tag = tagOctetString
elem.decoder = ctx.decodeOctetString
} else {
elem.tag = tagSequence
elem.decoder = ctx.decodeSlice
}
}
return
}
//
func (ctx *Context) getExpectedFieldElements(value reflect.Value) ([]expectedFieldElement, error) {
expectedValues := []expectedFieldElement{}
for i := 0; i < value.NumField(); i++ {
if value.CanSet() {
// Get field and options
field := value.Field(i)
opts, err := parseOptions(value.Type().Field(i).Tag.Get(tagKey))
if err != nil {
return nil, err
}
// Expand choices
raw := &rawValue{}
if opts.choice == nil {
elem, err := ctx.getExpectedElement(raw, field.Type(), opts)
if err != nil {
return nil, err
}
expectedValues = append(expectedValues,
expectedFieldElement{elem, field, opts})
} else {
entries, err := ctx.getChoices(*opts.choice)
if err != nil {
return nil, err
}
for _, entry := range entries {
raw.Class = entry.class
raw.Tag = entry.tag
elem, err := ctx.getExpectedElement(raw, field.Type(), opts)
if err != nil {
return nil, err
}
expectedValues = append(expectedValues,
expectedFieldElement{elem, field, opts})
}
}
}
}
return expectedValues, nil
}
// getRawValuesFromBytes reads up to max values from the byte sequence.
func (ctx *Context) getRawValuesFromBytes(data []byte, max int) ([]*rawValue, error) {
// Raw values
rawValues := []*rawValue{}
reader := bytes.NewBuffer(data)
for i := 0; i < max; i++ {
// Parse an Asn.1 element
raw, err := decodeRawValue(reader)
if err != nil {
return nil, err
}
rawValues = append(rawValues, raw)
if reader.Len() == 0 {
return rawValues, nil
}
}
return nil, parseError("too many items for Sequence")
}
// matchExpectedValues tries to decode a sequence of raw values based on the
// expected elements.
func (ctx *Context) matchExpectedValues(eValues []expectedFieldElement, rValues []*rawValue) error {
// Try to match expected and raw values
rIndex := 0
for eIndex := 0; eIndex < len(eValues); eIndex++ {
e := eValues[eIndex]
// Using nil decoder to skip matched choices
if e.decoder == nil {
continue
}
missing := true
if rIndex < len(rValues) {
raw := rValues[rIndex]
if e.class == raw.Class && e.tag == raw.Tag {
err := e.decoder(raw.Content, e.value)
if err != nil {
return err
}
// Mark as found and advance raw values index
missing = false
rIndex++
// Remove other options for the matched choice
if e.opts.choice != nil {
for i := eIndex + 1; i < len(eValues); i++ {
c := eValues[i].opts.choice
if c != nil && *c == *e.opts.choice {
eValues[i].decoder = nil
}
}
}
}
}
if missing {
if err := ctx.setMissingFieldValue(e); err != nil {
return err
}
}
}
return nil
}
// setMissingFieldValue uses opts values to set the default value.
func (ctx *Context) setMissingFieldValue(e expectedFieldElement) error {
if e.opts.optional || e.opts.choice != nil {
return nil
}
if e.opts.defaultValue != nil {
err := ctx.setDefaultValue(e.value, e.opts)
if err != nil {
return err
}
return nil
}
return parseError("missing value for [%d %d]", e.class, e.tag)
}
// decodeStruct decodes struct fields in order
func (ctx *Context) decodeStruct(data []byte, value reflect.Value) error {
expectedValues, err := ctx.getExpectedFieldElements(value)
if err != nil {
return err
}
rawValues, err := ctx.getRawValuesFromBytes(data, len(expectedValues))
if err != nil {
return err
}
return ctx.matchExpectedValues(expectedValues, rawValues)
}
// Decode a struct as an Asn.1 Set.
//
// The order doesn't matter for set. However DER dictates that a Set should be
// encoded in the ascending order of the tags. So when decoding with DER, we
// simply do not sort the raw values and use them in their natural order.
func (ctx *Context) decodeStructAsSet(data []byte, value reflect.Value) error {
// Get the expected values
expectedElements, err := ctx.getExpectedFieldElements(value)
if err != nil {
return err
}
sort.Sort(expectedFieldElementSlice(expectedElements))
// Check duplicated tags
for i := 1; i < len(expectedElements); i++ {
curr := expectedElements[i]
prev := expectedElements[i-1]
if curr.class == prev.class &&
curr.tag == prev.tag {
return syntaxError("duplicated tag (%d,%d)", curr.class, curr.tag)
}
}
// Get the raw values
rawValues, err := ctx.getRawValuesFromBytes(data, len(expectedElements))
if err != nil {
return err
}
if !ctx.der.decoding {
sort.Sort(rawValueSlice(rawValues))
}
return ctx.matchExpectedValues(expectedElements, rawValues)
}
// decodeSlice decodes a SET(OF) as a slice
func (ctx *Context) decodeSlice(data []byte, value reflect.Value) error {
slice := reflect.New(value.Type()).Elem()
var err error
for len(data) > 0 {
elem := reflect.New(value.Type().Elem()).Elem()
data, err = ctx.DecodeWithOptions(data, elem.Addr().Interface(), "")
if err != nil {
return err
}
slice.Set(reflect.Append(slice, elem))
}
value.Set(slice)
return nil
}
// decodeArray decodes a SET(OF) as an array
func (ctx *Context) decodeArray(data []byte, value reflect.Value) error {
var err error
for i := 0; i < value.Len(); i++ {
if len(data) == 0 {
return parseError("missing elements")
}
elem := reflect.New(value.Type().Elem()).Elem()
data, err = ctx.DecodeWithOptions(data, elem.Addr().Interface(), "")
if err != nil {
return err
}
value.Index(i).Set(elem)
}
if len(data) > 0 {
return parseError("too many elements")
}
return nil
}