1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package tls
20
21 import (
22 "bytes"
23 "encoding/binary"
24 "fmt"
25 "reflect"
26 "strconv"
27 "strings"
28 )
29
30
31
32
33
34
35 type structuralError struct {
36 field string
37 msg string
38 }
39
40 func (e structuralError) Error() string {
41 var prefix string
42 if e.field != "" {
43 prefix = e.field + ": "
44 }
45 return "tls: structure error: " + prefix + e.msg
46 }
47
48
49 type syntaxError struct {
50 field string
51 msg string
52 }
53
54 func (e syntaxError) Error() string {
55 var prefix string
56 if e.field != "" {
57 prefix = e.field + ": "
58 }
59 return "tls: syntax error: " + prefix + e.msg
60 }
61
62
63 type Uint24 uint32
64
65
66 type Enum uint64
67
68 var (
69 uint8Type = reflect.TypeOf(uint8(0))
70 uint16Type = reflect.TypeOf(uint16(0))
71 uint24Type = reflect.TypeOf(Uint24(0))
72 uint32Type = reflect.TypeOf(uint32(0))
73 uint64Type = reflect.TypeOf(uint64(0))
74 enumType = reflect.TypeOf(Enum(0))
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 func Unmarshal(b []byte, val interface{}) ([]byte, error) {
147 return UnmarshalWithParams(b, val, "")
148 }
149
150
151
152 func UnmarshalWithParams(b []byte, val interface{}, params string) ([]byte, error) {
153 info, err := fieldTagToFieldInfo(params, "")
154 if err != nil {
155 return nil, err
156 }
157
158
159
160 v := reflect.ValueOf(val).Elem()
161 offset, err := parseField(v, b, 0, info)
162 if err != nil {
163 return nil, err
164 }
165 return b[offset:], nil
166 }
167
168
169 func byteCount(x uint64) uint {
170 switch {
171 case x < 0x100:
172 return 1
173 case x < 0x10000:
174 return 2
175 case x < 0x1000000:
176 return 3
177 case x < 0x100000000:
178 return 4
179 case x < 0x10000000000:
180 return 5
181 case x < 0x1000000000000:
182 return 6
183 case x < 0x100000000000000:
184 return 7
185 default:
186 return 8
187 }
188 }
189
190 type fieldInfo struct {
191 count uint
192 countSet bool
193 minlen uint64
194 maxlen uint64
195 selector string
196 val uint64
197 name string
198 }
199
200 func (i *fieldInfo) fieldName() string {
201 if i == nil {
202 return ""
203 }
204 return i.name
205 }
206
207
208 func fieldTagToFieldInfo(str string, name string) (*fieldInfo, error) {
209 var info *fieldInfo
210
211 for _, part := range strings.Split(str, ",") {
212 switch {
213 case strings.HasPrefix(part, "maxval:"):
214 if v, err := strconv.ParseUint(part[7:], 10, 64); err == nil {
215 info = &fieldInfo{count: byteCount(v), countSet: true}
216 }
217 case strings.HasPrefix(part, "size:"):
218 if sz, err := strconv.ParseUint(part[5:], 10, 32); err == nil {
219 info = &fieldInfo{count: uint(sz), countSet: true}
220 }
221 case strings.HasPrefix(part, "maxlen:"):
222 v, err := strconv.ParseUint(part[7:], 10, 64)
223 if err != nil {
224 continue
225 }
226 if info == nil {
227 info = &fieldInfo{}
228 }
229 info.count = byteCount(v)
230 info.countSet = true
231 info.maxlen = v
232 case strings.HasPrefix(part, "minlen:"):
233 v, err := strconv.ParseUint(part[7:], 10, 64)
234 if err != nil {
235 continue
236 }
237 if info == nil {
238 info = &fieldInfo{}
239 }
240 info.minlen = v
241 case strings.HasPrefix(part, "selector:"):
242 if info == nil {
243 info = &fieldInfo{}
244 }
245 info.selector = part[9:]
246 case strings.HasPrefix(part, "val:"):
247 v, err := strconv.ParseUint(part[4:], 10, 64)
248 if err != nil {
249 continue
250 }
251 if info == nil {
252 info = &fieldInfo{}
253 }
254 info.val = v
255 }
256 }
257 if info != nil {
258 info.name = name
259 if info.selector == "" {
260 if info.count < 1 {
261 return nil, structuralError{name, "field of unknown size in " + str}
262 } else if info.count > 8 {
263 return nil, structuralError{name, "specified size too large in " + str}
264 } else if info.minlen > info.maxlen {
265 return nil, structuralError{name, "specified length range inverted in " + str}
266 } else if info.val > 0 {
267 return nil, structuralError{name, "specified selector value but not field in " + str}
268 }
269 }
270 } else if name != "" {
271 info = &fieldInfo{name: name}
272 }
273 return info, nil
274 }
275
276
277 func (i fieldInfo) check(val uint64, fldName string) error {
278 if val >= (1 << (8 * i.count)) {
279 return structuralError{fldName, fmt.Sprintf("value %d too large for size", val)}
280 }
281 if i.maxlen != 0 {
282 if val < i.minlen {
283 return structuralError{fldName, fmt.Sprintf("value %d too small for minimum %d", val, i.minlen)}
284 }
285 if val > i.maxlen {
286 return structuralError{fldName, fmt.Sprintf("value %d too large for maximum %d", val, i.maxlen)}
287 }
288 }
289 return nil
290 }
291
292
293
294 func readVarUint(data []byte, info *fieldInfo) (uint64, error) {
295 if info == nil || !info.countSet {
296 return 0, structuralError{info.fieldName(), "no field size information available"}
297 }
298 if len(data) < int(info.count) {
299 return 0, syntaxError{info.fieldName(), "truncated variable-length integer"}
300 }
301 var result uint64
302 for i := uint(0); i < info.count; i++ {
303 result = (result << 8) | uint64(data[i])
304 }
305 if err := info.check(result, info.name); err != nil {
306 return 0, err
307 }
308 return result, nil
309 }
310
311
312
313
314 func parseField(v reflect.Value, data []byte, initOffset int, info *fieldInfo) (int, error) {
315 offset := initOffset
316 rest := data[offset:]
317
318 fieldType := v.Type()
319
320 switch fieldType {
321 case uint8Type:
322 if len(rest) < 1 {
323 return offset, syntaxError{info.fieldName(), "truncated uint8"}
324 }
325 v.SetUint(uint64(rest[0]))
326 offset++
327 return offset, nil
328 case uint16Type:
329 if len(rest) < 2 {
330 return offset, syntaxError{info.fieldName(), "truncated uint16"}
331 }
332 v.SetUint(uint64(binary.BigEndian.Uint16(rest)))
333 offset += 2
334 return offset, nil
335 case uint24Type:
336 if len(rest) < 3 {
337 return offset, syntaxError{info.fieldName(), "truncated uint24"}
338 }
339 v.SetUint(uint64(data[0])<<16 | uint64(data[1])<<8 | uint64(data[2]))
340 offset += 3
341 return offset, nil
342 case uint32Type:
343 if len(rest) < 4 {
344 return offset, syntaxError{info.fieldName(), "truncated uint32"}
345 }
346 v.SetUint(uint64(binary.BigEndian.Uint32(rest)))
347 offset += 4
348 return offset, nil
349 case uint64Type:
350 if len(rest) < 8 {
351 return offset, syntaxError{info.fieldName(), "truncated uint64"}
352 }
353 v.SetUint(uint64(binary.BigEndian.Uint64(rest)))
354 offset += 8
355 return offset, nil
356 }
357
358
359 switch v.Kind() {
360 case enumType.Kind():
361
362
363 val, err := readVarUint(rest, info)
364 if err != nil {
365 return offset, err
366 }
367 v.SetUint(val)
368 offset += int(info.count)
369 return offset, nil
370 case reflect.Struct:
371 structType := fieldType
372
373
374
375
376
377
378
379
380
381
382
383
384 enums := make(map[string]uint64)
385
386
387 selectorSeen := make(map[string]bool)
388 for i := 0; i < structType.NumField(); i++ {
389
390 tag := structType.Field(i).Tag.Get("tls")
391 fieldInfo, err := fieldTagToFieldInfo(tag, structType.Field(i).Name)
392 if err != nil {
393 return offset, err
394 }
395
396 destination := v.Field(i)
397 if fieldInfo.selector != "" {
398
399
400 choice, ok := enums[fieldInfo.selector]
401 if !ok {
402 return offset, structuralError{fieldInfo.name, "selector not seen: " + fieldInfo.selector}
403 }
404 if structType.Field(i).Type.Kind() != reflect.Ptr {
405 return offset, structuralError{fieldInfo.name, "choice field not a pointer type"}
406 }
407
408 seen, ok := selectorSeen[fieldInfo.selector]
409 if !ok {
410 selectorSeen[fieldInfo.selector] = false
411 }
412 if choice != fieldInfo.val {
413
414
415 v.Field(i).Set(reflect.Zero(structType.Field(i).Type))
416 continue
417 }
418 if seen {
419
420
421 return offset, structuralError{fieldInfo.name, "duplicate selector value for " + fieldInfo.selector}
422 }
423 selectorSeen[fieldInfo.selector] = true
424
425 v.Field(i).Set(reflect.New(structType.Field(i).Type.Elem()))
426 destination = v.Field(i).Elem()
427 }
428 offset, err = parseField(destination, data, offset, fieldInfo)
429 if err != nil {
430 return offset, err
431 }
432
433
434 if structType.Field(i).Type.Kind() == enumType.Kind() {
435 enums[structType.Field(i).Name] = v.Field(i).Uint()
436 }
437
438 }
439
440
441
442 for selector, seen := range selectorSeen {
443 if !seen {
444 return offset, syntaxError{info.fieldName(), selector + ": unhandled value for selector"}
445 }
446 }
447 return offset, nil
448 case reflect.Array:
449 datalen := v.Len()
450
451 if datalen > len(rest) {
452 return offset, syntaxError{info.fieldName(), "truncated array"}
453 }
454 inner := rest[:datalen]
455 offset += datalen
456 if fieldType.Elem().Kind() != reflect.Uint8 {
457
458 return offset, structuralError{info.fieldName(), "unsupported array type: " + v.Type().String()}
459 }
460 reflect.Copy(v, reflect.ValueOf(inner))
461 return offset, nil
462
463 case reflect.Slice:
464 sliceType := fieldType
465
466
467 varlen, err := readVarUint(rest, info)
468 if err != nil {
469 return offset, err
470 }
471 datalen := int(varlen)
472 offset += int(info.count)
473 rest = rest[info.count:]
474
475 if datalen > len(rest) {
476 return offset, syntaxError{info.fieldName(), "truncated slice"}
477 }
478 inner := rest[:datalen]
479 offset += datalen
480 if fieldType.Elem().Kind() == reflect.Uint8 {
481
482 v.Set(reflect.MakeSlice(sliceType, datalen, datalen))
483 reflect.Copy(v, reflect.ValueOf(inner))
484 return offset, nil
485 }
486
487 v.Set(reflect.MakeSlice(sliceType, 0, datalen))
488 single := reflect.New(sliceType.Elem())
489 for innerOffset := 0; innerOffset < len(inner); {
490 var err error
491 innerOffset, err = parseField(single.Elem(), inner, innerOffset, nil)
492 if err != nil {
493 return offset, err
494 }
495 v.Set(reflect.Append(v, single.Elem()))
496 }
497 return offset, nil
498
499 default:
500 return offset, structuralError{info.fieldName(), fmt.Sprintf("unsupported type: %s of kind %s", fieldType, v.Kind())}
501 }
502 }
503
504
505 func Marshal(val interface{}) ([]byte, error) {
506 return MarshalWithParams(val, "")
507 }
508
509
510
511
512 func MarshalWithParams(val interface{}, params string) ([]byte, error) {
513 info, err := fieldTagToFieldInfo(params, "")
514 if err != nil {
515 return nil, err
516 }
517 var out bytes.Buffer
518 v := reflect.ValueOf(val)
519 if err := marshalField(&out, v, info); err != nil {
520 return nil, err
521 }
522 return out.Bytes(), err
523 }
524
525 func marshalField(out *bytes.Buffer, v reflect.Value, info *fieldInfo) error {
526 var prefix string
527 if info != nil && len(info.name) > 0 {
528 prefix = info.name + ": "
529 }
530 fieldType := v.Type()
531
532 switch fieldType {
533 case uint8Type:
534 out.WriteByte(byte(v.Uint()))
535 return nil
536 case uint16Type:
537 scratch := make([]byte, 2)
538 binary.BigEndian.PutUint16(scratch, uint16(v.Uint()))
539 out.Write(scratch)
540 return nil
541 case uint24Type:
542 i := v.Uint()
543 if i > 0xffffff {
544 return structuralError{info.fieldName(), fmt.Sprintf("uint24 overflow %d", i)}
545 }
546 scratch := make([]byte, 4)
547 binary.BigEndian.PutUint32(scratch, uint32(i))
548 out.Write(scratch[1:])
549 return nil
550 case uint32Type:
551 scratch := make([]byte, 4)
552 binary.BigEndian.PutUint32(scratch, uint32(v.Uint()))
553 out.Write(scratch)
554 return nil
555 case uint64Type:
556 scratch := make([]byte, 8)
557 binary.BigEndian.PutUint64(scratch, uint64(v.Uint()))
558 out.Write(scratch)
559 return nil
560 }
561
562
563 switch v.Kind() {
564 case enumType.Kind():
565 i := v.Uint()
566 if info == nil {
567 return structuralError{info.fieldName(), "enum field tag missing"}
568 }
569 if err := info.check(i, prefix); err != nil {
570 return err
571 }
572 scratch := make([]byte, 8)
573 binary.BigEndian.PutUint64(scratch, uint64(i))
574 out.Write(scratch[(8 - info.count):])
575 return nil
576 case reflect.Struct:
577 structType := fieldType
578 enums := make(map[string]uint64)
579
580
581
582
583
584 selectorSeen := make(map[string]bool)
585 for i := 0; i < structType.NumField(); i++ {
586
587 tag := structType.Field(i).Tag.Get("tls")
588 fieldInfo, err := fieldTagToFieldInfo(tag, structType.Field(i).Name)
589 if err != nil {
590 return err
591 }
592
593 source := v.Field(i)
594 if fieldInfo.selector != "" {
595
596
597 choice, ok := enums[fieldInfo.selector]
598 if !ok {
599 return structuralError{fieldInfo.name, "selector not seen: " + fieldInfo.selector}
600 }
601 if structType.Field(i).Type.Kind() != reflect.Ptr {
602 return structuralError{fieldInfo.name, "choice field not a pointer type"}
603 }
604
605 seen, ok := selectorSeen[fieldInfo.selector]
606 if !ok {
607 selectorSeen[fieldInfo.selector] = false
608 }
609 if choice != fieldInfo.val {
610
611 if v.Field(i).Pointer() != uintptr(0) {
612 return structuralError{fieldInfo.name, "unchosen field is non-nil"}
613 }
614 continue
615 }
616 if seen {
617
618
619 return structuralError{fieldInfo.name, "duplicate selector value for " + fieldInfo.selector}
620 }
621 selectorSeen[fieldInfo.selector] = true
622 if v.Field(i).Pointer() == uintptr(0) {
623 return structuralError{fieldInfo.name, "chosen field is nil"}
624 }
625
626 source = v.Field(i).Elem()
627 }
628
629 var fieldData bytes.Buffer
630 if err := marshalField(&fieldData, source, fieldInfo); err != nil {
631 return err
632 }
633 out.Write(fieldData.Bytes())
634
635
636 if structType.Field(i).Type.Kind() == enumType.Kind() {
637 enums[structType.Field(i).Name] = v.Field(i).Uint()
638 }
639 }
640
641
642 for selector, seen := range selectorSeen {
643 if !seen {
644 return syntaxError{info.fieldName(), selector + ": unhandled value for selector"}
645 }
646 }
647 return nil
648
649 case reflect.Array:
650 datalen := v.Len()
651 arrayType := fieldType
652 if arrayType.Elem().Kind() != reflect.Uint8 {
653
654 return structuralError{info.fieldName(), "unsupported array type"}
655 }
656 bytes := make([]byte, datalen)
657 for i := 0; i < datalen; i++ {
658 bytes[i] = uint8(v.Index(i).Uint())
659 }
660 _, err := out.Write(bytes)
661 return err
662
663 case reflect.Slice:
664 if info == nil {
665 return structuralError{info.fieldName(), "slice field tag missing"}
666 }
667
668 sliceType := fieldType
669 if sliceType.Elem().Kind() == reflect.Uint8 {
670
671 datalen := v.Len()
672 scratch := make([]byte, 8)
673 binary.BigEndian.PutUint64(scratch, uint64(datalen))
674 out.Write(scratch[(8 - info.count):])
675
676 if err := info.check(uint64(datalen), prefix); err != nil {
677 return err
678 }
679
680 bytes := make([]byte, datalen)
681 for i := 0; i < datalen; i++ {
682 bytes[i] = uint8(v.Index(i).Uint())
683 }
684 _, err := out.Write(bytes)
685 return err
686 }
687
688 var innerBuf bytes.Buffer
689 for i := 0; i < v.Len(); i++ {
690 if err := marshalField(&innerBuf, v.Index(i), nil); err != nil {
691 return err
692 }
693 }
694
695
696 size := uint64(innerBuf.Len())
697 if err := info.check(size, prefix); err != nil {
698 return err
699 }
700 scratch := make([]byte, 8)
701 binary.BigEndian.PutUint64(scratch, size)
702 out.Write(scratch[(8 - info.count):])
703
704
705 _, err := out.Write(innerBuf.Bytes())
706 return err
707
708 default:
709 return structuralError{info.fieldName(), fmt.Sprintf("unsupported type: %s of kind %s", fieldType, v.Kind())}
710 }
711 }
712
View as plain text