1 package pkcs7
2
3 import (
4 "bytes"
5 "errors"
6 )
7
8 type asn1Object interface {
9 EncodeTo(writer *bytes.Buffer) error
10 }
11
12 type asn1Structured struct {
13 tagBytes []byte
14 content []asn1Object
15 }
16
17 func (s asn1Structured) EncodeTo(out *bytes.Buffer) error {
18
19 inner := new(bytes.Buffer)
20 for _, obj := range s.content {
21 err := obj.EncodeTo(inner)
22 if err != nil {
23 return err
24 }
25 }
26 out.Write(s.tagBytes)
27 encodeLength(out, inner.Len())
28 out.Write(inner.Bytes())
29 return nil
30 }
31
32 type asn1Primitive struct {
33 tagBytes []byte
34 length int
35 content []byte
36 }
37
38 func (p asn1Primitive) EncodeTo(out *bytes.Buffer) error {
39 _, err := out.Write(p.tagBytes)
40 if err != nil {
41 return err
42 }
43 if err = encodeLength(out, p.length); err != nil {
44 return err
45 }
46
47
48 out.Write(p.content)
49
50 return nil
51 }
52
53 func ber2der(ber []byte) ([]byte, error) {
54 if len(ber) == 0 {
55 return nil, errors.New("ber2der: input ber is empty")
56 }
57
58 out := new(bytes.Buffer)
59
60 obj, _, err := readObject(ber, 0)
61 if err != nil {
62 return nil, err
63 }
64 obj.EncodeTo(out)
65
66 return out.Bytes(), nil
67 }
68
69
70 func marshalLongLength(out *bytes.Buffer, i int) (err error) {
71 n := lengthLength(i)
72
73 for ; n > 0; n-- {
74 err = out.WriteByte(byte(i >> uint((n-1)*8)))
75 if err != nil {
76 return
77 }
78 }
79
80 return nil
81 }
82
83
84 func lengthLength(i int) (numBytes int) {
85 numBytes = 1
86 for i > 255 {
87 numBytes++
88 i >>= 8
89 }
90 return
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 func encodeLength(out *bytes.Buffer, length int) (err error) {
108 if length >= 128 {
109 l := lengthLength(length)
110 err = out.WriteByte(0x80 | byte(l))
111 if err != nil {
112 return
113 }
114 err = marshalLongLength(out, length)
115 if err != nil {
116 return
117 }
118 } else {
119 err = out.WriteByte(byte(length))
120 if err != nil {
121 return
122 }
123 }
124 return
125 }
126
127 func readObject(ber []byte, offset int) (asn1Object, int, error) {
128 berLen := len(ber)
129 if offset >= berLen {
130 return nil, 0, errors.New("ber2der: offset is after end of ber data")
131 }
132 tagStart := offset
133 b := ber[offset]
134 offset++
135 if offset >= berLen {
136 return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
137 }
138 tag := b & 0x1F
139 if tag == 0x1F {
140 tag = 0
141 for ber[offset] >= 0x80 {
142 tag = tag*128 + ber[offset] - 0x80
143 offset++
144 if offset >= berLen {
145 return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
146 }
147 }
148
149
150 offset++
151 if offset >= berLen {
152 return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
153 }
154 }
155 tagEnd := offset
156
157 kind := b & 0x20
158 if kind == 0 {
159 debugprint("--> Primitive\n")
160 } else {
161 debugprint("--> Constructed\n")
162 }
163
164 var length int
165 l := ber[offset]
166 offset++
167 if l >= 0x80 && offset >= berLen {
168
169
170
171 return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
172 }
173 indefinite := false
174 if l > 0x80 {
175 numberOfBytes := (int)(l & 0x7F)
176 if numberOfBytes > 4 {
177 return nil, 0, errors.New("ber2der: BER tag length too long")
178 }
179 if numberOfBytes == 4 && (int)(ber[offset]) > 0x7F {
180 return nil, 0, errors.New("ber2der: BER tag length is negative")
181 }
182 if offset + numberOfBytes > berLen {
183
184
185 return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
186 }
187 if (int)(ber[offset]) == 0x0 && (numberOfBytes == 1 || ber[offset+1] <= 0x7F) {
188
189 return nil, 0, errors.New("ber2der: BER tag length has leading zero")
190 }
191 debugprint("--> (compute length) indicator byte: %x\n", l)
192
193 for i := 0; i < numberOfBytes; i++ {
194 length = length*256 + (int)(ber[offset])
195 offset++
196 }
197 } else if l == 0x80 {
198 indefinite = true
199 } else {
200 length = (int)(l)
201 }
202 if length < 0 {
203 return nil, 0, errors.New("ber2der: invalid negative value found in BER tag length")
204 }
205
206 contentEnd := offset + length
207 if contentEnd > berLen {
208 return nil, 0, errors.New("ber2der: BER tag length is more than available data")
209 }
210 debugprint("--> content start : %d\n", offset)
211 debugprint("--> content end : %d\n", contentEnd)
212
213 var obj asn1Object
214 if indefinite && kind == 0 {
215 return nil, 0, errors.New("ber2der: Indefinite form tag must have constructed encoding")
216 }
217 if kind == 0 {
218 obj = asn1Primitive{
219 tagBytes: ber[tagStart:tagEnd],
220 length: length,
221 content: ber[offset:contentEnd],
222 }
223 } else {
224 var subObjects []asn1Object
225 for (offset < contentEnd) || indefinite {
226 var subObj asn1Object
227 var err error
228 subObj, offset, err = readObject(ber, offset)
229 if err != nil {
230 return nil, 0, err
231 }
232 subObjects = append(subObjects, subObj)
233
234 if indefinite {
235 terminated, err := isIndefiniteTermination(ber, offset)
236 if err != nil {
237 return nil, 0, err
238 }
239
240 if terminated {
241 break
242 }
243 }
244 }
245 obj = asn1Structured{
246 tagBytes: ber[tagStart:tagEnd],
247 content: subObjects,
248 }
249 }
250
251
252 if indefinite {
253 contentEnd = offset + 2
254 }
255
256 return obj, contentEnd, nil
257 }
258
259 func isIndefiniteTermination(ber []byte, offset int) (bool, error) {
260 if len(ber) - offset < 2 {
261 return false, errors.New("ber2der: Invalid BER format")
262 }
263
264 return bytes.Index(ber[offset:], []byte{0x0, 0x0}) == 0, nil
265 }
266
267 func debugprint(format string, a ...interface{}) {
268
269 }
270
View as plain text