Source file src/pkg/encoding/asn1/marshal.go
1
2
3
4
5 package asn1
6
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "io"
12 "math/big"
13 "reflect"
14 "time"
15 "unicode/utf8"
16 )
17
18
19
20
21
22
23 type forkableWriter struct {
24 *bytes.Buffer
25 pre, post *forkableWriter
26 }
27
28 func newForkableWriter() *forkableWriter {
29 return &forkableWriter{new(bytes.Buffer), nil, nil}
30 }
31
32 func (f *forkableWriter) fork() (pre, post *forkableWriter) {
33 if f.pre != nil || f.post != nil {
34 panic("have already forked")
35 }
36 f.pre = newForkableWriter()
37 f.post = newForkableWriter()
38 return f.pre, f.post
39 }
40
41 func (f *forkableWriter) Len() (l int) {
42 l += f.Buffer.Len()
43 if f.pre != nil {
44 l += f.pre.Len()
45 }
46 if f.post != nil {
47 l += f.post.Len()
48 }
49 return
50 }
51
52 func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) {
53 n, err = out.Write(f.Bytes())
54 if err != nil {
55 return
56 }
57
58 var nn int
59
60 if f.pre != nil {
61 nn, err = f.pre.writeTo(out)
62 n += nn
63 if err != nil {
64 return
65 }
66 }
67
68 if f.post != nil {
69 nn, err = f.post.writeTo(out)
70 n += nn
71 }
72 return
73 }
74
75 func marshalBase128Int(out *forkableWriter, n int64) (err error) {
76 if n == 0 {
77 err = out.WriteByte(0)
78 return
79 }
80
81 l := 0
82 for i := n; i > 0; i >>= 7 {
83 l++
84 }
85
86 for i := l - 1; i >= 0; i-- {
87 o := byte(n >> uint(i*7))
88 o &= 0x7f
89 if i != 0 {
90 o |= 0x80
91 }
92 err = out.WriteByte(o)
93 if err != nil {
94 return
95 }
96 }
97
98 return nil
99 }
100
101 func marshalInt64(out *forkableWriter, i int64) (err error) {
102 n := int64Length(i)
103
104 for ; n > 0; n-- {
105 err = out.WriteByte(byte(i >> uint((n-1)*8)))
106 if err != nil {
107 return
108 }
109 }
110
111 return nil
112 }
113
114 func int64Length(i int64) (numBytes int) {
115 numBytes = 1
116
117 for i > 127 {
118 numBytes++
119 i >>= 8
120 }
121
122 for i < -128 {
123 numBytes++
124 i >>= 8
125 }
126
127 return
128 }
129
130 func marshalBigInt(out *forkableWriter, n *big.Int) (err error) {
131 if n.Sign() < 0 {
132
133
134
135
136 nMinus1 := new(big.Int).Neg(n)
137 nMinus1.Sub(nMinus1, bigOne)
138 bytes := nMinus1.Bytes()
139 for i := range bytes {
140 bytes[i] ^= 0xff
141 }
142 if len(bytes) == 0 || bytes[0]&0x80 == 0 {
143 err = out.WriteByte(0xff)
144 if err != nil {
145 return
146 }
147 }
148 _, err = out.Write(bytes)
149 } else if n.Sign() == 0 {
150
151 err = out.WriteByte(0x00)
152 } else {
153 bytes := n.Bytes()
154 if len(bytes) > 0 && bytes[0]&0x80 != 0 {
155
156
157 err = out.WriteByte(0)
158 if err != nil {
159 return
160 }
161 }
162 _, err = out.Write(bytes)
163 }
164 return
165 }
166
167 func marshalLength(out *forkableWriter, i int) (err error) {
168 n := lengthLength(i)
169
170 for ; n > 0; n-- {
171 err = out.WriteByte(byte(i >> uint((n-1)*8)))
172 if err != nil {
173 return
174 }
175 }
176
177 return nil
178 }
179
180 func lengthLength(i int) (numBytes int) {
181 numBytes = 1
182 for i > 255 {
183 numBytes++
184 i >>= 8
185 }
186 return
187 }
188
189 func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) {
190 b := uint8(t.class) << 6
191 if t.isCompound {
192 b |= 0x20
193 }
194 if t.tag >= 31 {
195 b |= 0x1f
196 err = out.WriteByte(b)
197 if err != nil {
198 return
199 }
200 err = marshalBase128Int(out, int64(t.tag))
201 if err != nil {
202 return
203 }
204 } else {
205 b |= uint8(t.tag)
206 err = out.WriteByte(b)
207 if err != nil {
208 return
209 }
210 }
211
212 if t.length >= 128 {
213 l := lengthLength(t.length)
214 err = out.WriteByte(0x80 | byte(l))
215 if err != nil {
216 return
217 }
218 err = marshalLength(out, t.length)
219 if err != nil {
220 return
221 }
222 } else {
223 err = out.WriteByte(byte(t.length))
224 if err != nil {
225 return
226 }
227 }
228
229 return nil
230 }
231
232 func marshalBitString(out *forkableWriter, b BitString) (err error) {
233 paddingBits := byte((8 - b.BitLength%8) % 8)
234 err = out.WriteByte(paddingBits)
235 if err != nil {
236 return
237 }
238 _, err = out.Write(b.Bytes)
239 return
240 }
241
242 func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) {
243 if len(oid) < 2 || oid[0] > 6 || oid[1] >= 40 {
244 return StructuralError{"invalid object identifier"}
245 }
246
247 err = out.WriteByte(byte(oid[0]*40 + oid[1]))
248 if err != nil {
249 return
250 }
251 for i := 2; i < len(oid); i++ {
252 err = marshalBase128Int(out, int64(oid[i]))
253 if err != nil {
254 return
255 }
256 }
257
258 return
259 }
260
261 func marshalPrintableString(out *forkableWriter, s string) (err error) {
262 b := []byte(s)
263 for _, c := range b {
264 if !isPrintable(c) {
265 return StructuralError{"PrintableString contains invalid character"}
266 }
267 }
268
269 _, err = out.Write(b)
270 return
271 }
272
273 func marshalIA5String(out *forkableWriter, s string) (err error) {
274 b := []byte(s)
275 for _, c := range b {
276 if c > 127 {
277 return StructuralError{"IA5String contains invalid character"}
278 }
279 }
280
281 _, err = out.Write(b)
282 return
283 }
284
285 func marshalUTF8String(out *forkableWriter, s string) (err error) {
286 _, err = out.Write([]byte(s))
287 return
288 }
289
290 func marshalTwoDigits(out *forkableWriter, v int) (err error) {
291 err = out.WriteByte(byte('0' + (v/10)%10))
292 if err != nil {
293 return
294 }
295 return out.WriteByte(byte('0' + v%10))
296 }
297
298 func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
299 year, month, day := t.Date()
300
301 switch {
302 case 1950 <= year && year < 2000:
303 err = marshalTwoDigits(out, int(year-1900))
304 case 2000 <= year && year < 2050:
305 err = marshalTwoDigits(out, int(year-2000))
306 default:
307 return StructuralError{"Cannot represent time as UTCTime"}
308 }
309 if err != nil {
310 return
311 }
312
313 err = marshalTwoDigits(out, int(month))
314 if err != nil {
315 return
316 }
317
318 err = marshalTwoDigits(out, day)
319 if err != nil {
320 return
321 }
322
323 hour, min, sec := t.Clock()
324
325 err = marshalTwoDigits(out, hour)
326 if err != nil {
327 return
328 }
329
330 err = marshalTwoDigits(out, min)
331 if err != nil {
332 return
333 }
334
335 err = marshalTwoDigits(out, sec)
336 if err != nil {
337 return
338 }
339
340 _, offset := t.Zone()
341
342 switch {
343 case offset/60 == 0:
344 err = out.WriteByte('Z')
345 return
346 case offset > 0:
347 err = out.WriteByte('+')
348 case offset < 0:
349 err = out.WriteByte('-')
350 }
351
352 if err != nil {
353 return
354 }
355
356 offsetMinutes := offset / 60
357 if offsetMinutes < 0 {
358 offsetMinutes = -offsetMinutes
359 }
360
361 err = marshalTwoDigits(out, offsetMinutes/60)
362 if err != nil {
363 return
364 }
365
366 err = marshalTwoDigits(out, offsetMinutes%60)
367 return
368 }
369
370 func stripTagAndLength(in []byte) []byte {
371 _, offset, err := parseTagAndLength(in, 0)
372 if err != nil {
373 return in
374 }
375 return in[offset:]
376 }
377
378 func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) {
379 switch value.Type() {
380 case timeType:
381 return marshalUTCTime(out, value.Interface().(time.Time))
382 case bitStringType:
383 return marshalBitString(out, value.Interface().(BitString))
384 case objectIdentifierType:
385 return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
386 case bigIntType:
387 return marshalBigInt(out, value.Interface().(*big.Int))
388 }
389
390 switch v := value; v.Kind() {
391 case reflect.Bool:
392 if v.Bool() {
393 return out.WriteByte(255)
394 } else {
395 return out.WriteByte(0)
396 }
397 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
398 return marshalInt64(out, int64(v.Int()))
399 case reflect.Struct:
400 t := v.Type()
401
402 startingField := 0
403
404
405
406 if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
407 s := v.Field(0)
408 if s.Len() > 0 {
409 bytes := make([]byte, s.Len())
410 for i := 0; i < s.Len(); i++ {
411 bytes[i] = uint8(s.Index(i).Uint())
412 }
413 414 415 416
417 _, err = out.Write(stripTagAndLength(bytes))
418 return
419 } else {
420 startingField = 1
421 }
422 }
423
424 for i := startingField; i < t.NumField(); i++ {
425 var pre *forkableWriter
426 pre, out = out.fork()
427 err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
428 if err != nil {
429 return
430 }
431 }
432 return
433 case reflect.Slice:
434 sliceType := v.Type()
435 if sliceType.Elem().Kind() == reflect.Uint8 {
436 bytes := make([]byte, v.Len())
437 for i := 0; i < v.Len(); i++ {
438 bytes[i] = uint8(v.Index(i).Uint())
439 }
440 _, err = out.Write(bytes)
441 return
442 }
443
444 var params fieldParameters
445 for i := 0; i < v.Len(); i++ {
446 var pre *forkableWriter
447 pre, out = out.fork()
448 err = marshalField(pre, v.Index(i), params)
449 if err != nil {
450 return
451 }
452 }
453 return
454 case reflect.String:
455 switch params.stringType {
456 case tagIA5String:
457 return marshalIA5String(out, v.String())
458 case tagPrintableString:
459 return marshalPrintableString(out, v.String())
460 default:
461 return marshalUTF8String(out, v.String())
462 }
463 }
464
465 return StructuralError{"unknown Go type"}
466 }
467
468 func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) {
469
470 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
471 return marshalField(out, v.Elem(), params)
472 }
473
474 if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
475 return
476 }
477
478 if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
479 return
480 }
481
482 if v.Type() == rawValueType {
483 rv := v.Interface().(RawValue)
484 if len(rv.FullBytes) != 0 {
485 _, err = out.Write(rv.FullBytes)
486 } else {
487 err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
488 if err != nil {
489 return
490 }
491 _, err = out.Write(rv.Bytes)
492 }
493 return
494 }
495
496 tag, isCompound, ok := getUniversalType(v.Type())
497 if !ok {
498 err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
499 return
500 }
501 class := classUniversal
502
503 if params.stringType != 0 && tag != tagPrintableString {
504 return StructuralError{"Explicit string type given to non-string member"}
505 }
506
507 if tag == tagPrintableString {
508 if params.stringType == 0 {
509
510
511
512 for _, r := range v.String() {
513 if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
514 if !utf8.ValidString(v.String()) {
515 return errors.New("asn1: string not valid UTF-8")
516 }
517 tag = tagUTF8String
518 break
519 }
520 }
521 } else {
522 tag = params.stringType
523 }
524 }
525
526 if params.set {
527 if tag != tagSequence {
528 return StructuralError{"Non sequence tagged as set"}
529 }
530 tag = tagSet
531 }
532
533 tags, body := out.fork()
534
535 err = marshalBody(body, v, params)
536 if err != nil {
537 return
538 }
539
540 bodyLen := body.Len()
541
542 var explicitTag *forkableWriter
543 if params.explicit {
544 explicitTag, tags = tags.fork()
545 }
546
547 if !params.explicit && params.tag != nil {
548
549 tag = *params.tag
550 class = classContextSpecific
551 }
552
553 err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
554 if err != nil {
555 return
556 }
557
558 if params.explicit {
559 err = marshalTagAndLength(explicitTag, tagAndLength{
560 class: classContextSpecific,
561 tag: *params.tag,
562 length: bodyLen + tags.Len(),
563 isCompound: true,
564 })
565 }
566
567 return nil
568 }
569
570
571 func Marshal(val interface{}) ([]byte, error) {
572 var out bytes.Buffer
573 v := reflect.ValueOf(val)
574 f := newForkableWriter()
575 err := marshalField(f, v, fieldParameters{})
576 if err != nil {
577 return nil, err
578 }
579 _, err = f.writeTo(&out)
580 return out.Bytes(), nil
581 }
View as plain text