OSDN Git Service

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