-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse_ber.go
120 lines (100 loc) · 2.25 KB
/
parse_ber.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
package tlv
import (
"encoding/binary"
"errors"
)
func ParseBER(data []byte) (TLV, error) {
var err error
var result TLV
for len(data) > 0 {
var tag Tag
tag, data, err = parseBERTag(data)
if err != nil {
return result, err
}
var length int
length, data, err = parseBERLength(data)
if err != nil {
return result, err
}
var value []byte
value, data, err = parseValue(data, length)
if err != nil {
return result, err
}
result = append(result, Entry{
Tag: Tag(tag),
Length: length,
Value: value,
})
}
return result, nil
}
func ParseBERTL(data []byte) (TL, error) {
var err error
var result TL
for len(data) > 0 {
var tag Tag
tag, data, err = parseBERTag(data)
if err != nil {
return result, err
}
var length int
length, data, err = parseBERLength(data)
if err != nil {
return result, err
}
result = append(result, TLEntry{
Tag: Tag(tag),
Length: length,
})
}
return result, nil
}
func parseBERTag(data []byte) (tag Tag, remaining []byte, err error) {
if len(data) == 0 {
return 0, nil, errors.New("incomplete BER TLV: missing length")
}
b0 := data[0]
data = data[1:]
tagnum := int(b0)
if b0&0b0001_1111 == 0b0001_1111 {
for i := 0; i < 2; i++ {
bN := data[0]
data = data[1:]
tagnum *= 256
tagnum += int(bN)
isLastByte := bN&0b1000_0000 == 0
if isLastByte {
break
}
}
}
tag = Tag(tagnum)
return tag, data, nil
}
func parseBERLength(data []byte) (b0 int, remaining []byte, err error) {
if len(data) == 0 {
return 0, nil, errors.New("incomplete BER TLV: missing length")
}
b0 = int(data[0])
data = data[1:]
if b0 < 0x80 {
return b0, data, nil
}
if b0 == 0x80 || b0 >= 0x85 {
return 0, nil, errors.New("incomplete BER TLV: first byte of the length is invalid")
}
howmany := b0 & 0x0F
lenBytes := append(make([]byte, 8-howmany), data[:howmany]...)
data = data[howmany:]
return int(binary.BigEndian.Uint64(lenBytes)), data, nil
}
func parseValue(data []byte, length int) (value []byte, remaining []byte, err error) {
if len(data) < length {
return nil, nil, errors.New("incomplete BER TLV: expected length is bigger than the length of the remaining data")
}
value = data[:length]
data = data[length:]
return value, data, nil
}