Codebase list golang-gopkg-asn1-ber.v1 / 338a9bd
New upstream version 1.5.1 Alexandre Viau 3 years ago
21 changed file(s) with 830 addition(s) and 173 deletion(s). Raw diff Collapse all Expand all
00 language: go
1
12 go:
2 - 1.2
3 - 1.3
4 - 1.4
5 - 1.5
6 - 1.6
7 - 1.7
8 - 1.8
9 - tip
10 go_import_path: gopkg.in/asn-ber.v1
11 install:
12 - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
13 - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
14 - go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
15 - go build -v ./...
3 - 1.2.x
4 - 1.6.x
5 - 1.9.x
6 - 1.10.x
7 - 1.11.x
8 - 1.12.x
9 - 1.14.x
10 - tip
11
12 os:
13 - linux
14
15 arch:
16 - amd64
17
18 dist: xenial
19
20 env:
21 - GOARCH=amd64
22
23 jobs:
24 include:
25 - os: windows
26 go: 1.14.x
27 - os: osx
28 go: 1.14.x
29 - os: linux
30 go: 1.14.x
31 arch: arm64
32 - os: linux
33 go: 1.14.x
34 env:
35 - GOARCH=386
36
1637 script:
17 - go test -v -cover ./...
38 - go test -v -cover ./... || go test -v ./...
+191
-75
ber.go less more
44 "errors"
55 "fmt"
66 "io"
7 "math"
78 "os"
89 "reflect"
10 "time"
11 "unicode/utf8"
912 )
13
14 // MaxPacketLengthBytes specifies the maximum allowed packet size when calling ReadPacket or DecodePacket. Set to 0 for
15 // no limit.
16 var MaxPacketLengthBytes int64 = math.MaxInt32
1017
1118 type Packet struct {
1219 Identifier
137144 TypeConstructed: "Constructed",
138145 }
139146
140 var Debug bool = false
147 var Debug = false
141148
142149 func PrintBytes(out io.Writer, buf []byte, indent string) {
143 data_lines := make([]string, (len(buf)/30)+1)
144 num_lines := make([]string, (len(buf)/30)+1)
150 dataLines := make([]string, (len(buf)/30)+1)
151 numLines := make([]string, (len(buf)/30)+1)
145152
146153 for i, b := range buf {
147 data_lines[i/30] += fmt.Sprintf("%02x ", b)
148 num_lines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)
149 }
150
151 for i := 0; i < len(data_lines); i++ {
152 out.Write([]byte(indent + data_lines[i] + "\n"))
153 out.Write([]byte(indent + num_lines[i] + "\n\n"))
154 }
154 dataLines[i/30] += fmt.Sprintf("%02x ", b)
155 numLines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)
156 }
157
158 for i := 0; i < len(dataLines); i++ {
159 _, _ = out.Write([]byte(indent + dataLines[i] + "\n"))
160 _, _ = out.Write([]byte(indent + numLines[i] + "\n\n"))
161 }
162 }
163
164 func WritePacket(out io.Writer, p *Packet) {
165 printPacket(out, p, 0, false)
155166 }
156167
157168 func PrintPacket(p *Packet) {
159170 }
160171
161172 func printPacket(out io.Writer, p *Packet, indent int, printBytes bool) {
162 indent_str := ""
163
164 for len(indent_str) != indent {
165 indent_str += " "
166 }
167
168 class_str := ClassMap[p.ClassType]
169
170 tagtype_str := TypeMap[p.TagType]
171
172 tag_str := fmt.Sprintf("0x%02X", p.Tag)
173 indentStr := ""
174
175 for len(indentStr) != indent {
176 indentStr += " "
177 }
178
179 classStr := ClassMap[p.ClassType]
180
181 tagTypeStr := TypeMap[p.TagType]
182
183 tagStr := fmt.Sprintf("0x%02X", p.Tag)
173184
174185 if p.ClassType == ClassUniversal {
175 tag_str = tagMap[p.Tag]
186 tagStr = tagMap[p.Tag]
176187 }
177188
178189 value := fmt.Sprint(p.Value)
182193 description = p.Description + ": "
183194 }
184195
185 fmt.Fprintf(out, "%s%s(%s, %s, %s) Len=%d %q\n", indent_str, description, class_str, tagtype_str, tag_str, p.Data.Len(), value)
196 _, _ = fmt.Fprintf(out, "%s%s(%s, %s, %s) Len=%d %q\n", indentStr, description, classStr, tagTypeStr, tagStr, p.Data.Len(), value)
186197
187198 if printBytes {
188 PrintBytes(out, p.Bytes(), indent_str)
199 PrintBytes(out, p.Bytes(), indentStr)
189200 }
190201
191202 for _, child := range p.Children {
193204 }
194205 }
195206
196 // ReadPacket reads a single Packet from the reader
207 // ReadPacket reads a single Packet from the reader.
197208 func ReadPacket(reader io.Reader) (*Packet, error) {
198209 p, _, err := readPacket(reader)
199210 if err != nil {
206217 return string(data)
207218 }
208219
209 func parseInt64(bytes []byte) (ret int64, err error) {
220 func ParseInt64(bytes []byte) (ret int64, err error) {
210221 if len(bytes) > 8 {
211222 // We'll overflow an int64 in this case.
212223 err = fmt.Errorf("integer too large")
229240
230241 var j int
231242 for ; n > 0; n-- {
232 out[j] = (byte(i >> uint((n-1)*8)))
243 out[j] = byte(i >> uint((n-1)*8))
233244 j++
234245 }
235246
261272 }
262273
263274 // DecodePacketErr decodes the given bytes into a single Packet
264 // If a decode error is encountered, nil is returned
275 // If a decode error is encountered, nil is returned.
265276 func DecodePacketErr(data []byte) (*Packet, error) {
266277 p, _, err := readPacket(bytes.NewBuffer(data))
267278 if err != nil {
270281 return p, nil
271282 }
272283
273 // readPacket reads a single Packet from the reader, returning the number of bytes read
284 // readPacket reads a single Packet from the reader, returning the number of bytes read.
274285 func readPacket(reader io.Reader) (*Packet, int, error) {
275286 identifier, length, read, err := readHeader(reader)
276287 if err != nil {
329340 }
330341
331342 // Read definite-length content
332 content := make([]byte, length, length)
343 if MaxPacketLengthBytes > 0 && int64(length) > MaxPacketLengthBytes {
344 return nil, read, fmt.Errorf("length %d greater than maximum %d", length, MaxPacketLengthBytes)
345 }
346 content := make([]byte, length)
333347 if length > 0 {
334348 _, err := io.ReadFull(reader, content)
335349 if err != nil {
348362 switch p.Tag {
349363 case TagEOC:
350364 case TagBoolean:
351 val, _ := parseInt64(content)
365 val, _ := ParseInt64(content)
352366
353367 p.Value = val != 0
354368 case TagInteger:
355 p.Value, _ = parseInt64(content)
369 p.Value, _ = ParseInt64(content)
356370 case TagBitString:
357371 case TagOctetString:
358372 // the actual string encoding is not known here
364378 case TagObjectDescriptor:
365379 case TagExternal:
366380 case TagRealFloat:
381 p.Value, err = ParseReal(content)
367382 case TagEnumerated:
368 p.Value, _ = parseInt64(content)
383 p.Value, _ = ParseInt64(content)
369384 case TagEmbeddedPDV:
370385 case TagUTF8String:
371 p.Value = DecodeString(content)
386 val := DecodeString(content)
387 if !utf8.Valid([]byte(val)) {
388 err = errors.New("invalid UTF-8 string")
389 } else {
390 p.Value = val
391 }
372392 case TagRelativeOID:
373393 case TagSequence:
374394 case TagSet:
375395 case TagNumericString:
376396 case TagPrintableString:
377 p.Value = DecodeString(content)
397 val := DecodeString(content)
398 if err = isPrintableString(val); err == nil {
399 p.Value = val
400 }
378401 case TagT61String:
379402 case TagVideotexString:
380403 case TagIA5String:
404 val := DecodeString(content)
405 for i, c := range val {
406 if c >= 0x7F {
407 err = fmt.Errorf("invalid character for IA5String at pos %d: %c", i, c)
408 break
409 }
410 }
411 if err == nil {
412 p.Value = val
413 }
381414 case TagUTCTime:
382415 case TagGeneralizedTime:
416 p.Value, err = ParseGeneralizedTime(content)
383417 case TagGraphicString:
384418 case TagVisibleString:
385419 case TagGeneralString:
391425 p.Data.Write(content)
392426 }
393427
394 return p, read, nil
428 return p, read, err
429 }
430
431 func isPrintableString(val string) error {
432 for i, c := range val {
433 switch {
434 case c >= 'a' && c <= 'z':
435 case c >= 'A' && c <= 'Z':
436 case c >= '0' && c <= '9':
437 default:
438 switch c {
439 case '\'', '(', ')', '+', ',', '-', '.', '=', '/', ':', '?', ' ':
440 default:
441 return fmt.Errorf("invalid character in position %d", i)
442 }
443 }
444 }
445 return nil
395446 }
396447
397448 func (p *Packet) Bytes() []byte {
409460 p.Children = append(p.Children, child)
410461 }
411462
412 func Encode(ClassType Class, TagType Type, Tag Tag, Value interface{}, Description string) *Packet {
463 func Encode(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
413464 p := new(Packet)
414465
415 p.ClassType = ClassType
416 p.TagType = TagType
417 p.Tag = Tag
466 p.ClassType = classType
467 p.TagType = tagType
468 p.Tag = tag
418469 p.Data = new(bytes.Buffer)
419470
420471 p.Children = make([]*Packet, 0, 2)
421472
422 p.Value = Value
423 p.Description = Description
424
425 if Value != nil {
426 v := reflect.ValueOf(Value)
427
428 if ClassType == ClassUniversal {
429 switch Tag {
473 p.Value = value
474 p.Description = description
475
476 if value != nil {
477 v := reflect.ValueOf(value)
478
479 if classType == ClassUniversal {
480 switch tag {
430481 case TagOctetString:
431482 sv, ok := v.Interface().(string)
432483
433484 if ok {
434485 p.Data.Write([]byte(sv))
435486 }
487 case TagEnumerated:
488 bv, ok := v.Interface().([]byte)
489 if ok {
490 p.Data.Write(bv)
491 }
492 case TagEmbeddedPDV:
493 bv, ok := v.Interface().([]byte)
494 if ok {
495 p.Data.Write(bv)
496 }
497 }
498 } else if classType == ClassContext {
499 switch tag {
500 case TagEnumerated:
501 bv, ok := v.Interface().([]byte)
502 if ok {
503 p.Data.Write(bv)
504 }
505 case TagEmbeddedPDV:
506 bv, ok := v.Interface().([]byte)
507 if ok {
508 p.Data.Write(bv)
509 }
436510 }
437511 }
438512 }
439
440 return p
441 }
442
443 func NewSequence(Description string) *Packet {
444 return Encode(ClassUniversal, TypeConstructed, TagSequence, nil, Description)
445 }
446
447 func NewBoolean(ClassType Class, TagType Type, Tag Tag, Value bool, Description string) *Packet {
513 return p
514 }
515
516 func NewSequence(description string) *Packet {
517 return Encode(ClassUniversal, TypeConstructed, TagSequence, nil, description)
518 }
519
520 func NewBoolean(classType Class, tagType Type, tag Tag, value bool, description string) *Packet {
448521 intValue := int64(0)
449522
450 if Value {
523 if value {
451524 intValue = 1
452525 }
453526
454 p := Encode(ClassType, TagType, Tag, nil, Description)
455
456 p.Value = Value
527 p := Encode(classType, tagType, tag, nil, description)
528
529 p.Value = value
457530 p.Data.Write(encodeInteger(intValue))
458531
459532 return p
460533 }
461534
462 func NewInteger(ClassType Class, TagType Type, Tag Tag, Value interface{}, Description string) *Packet {
463 p := Encode(ClassType, TagType, Tag, nil, Description)
464
465 p.Value = Value
466 switch v := Value.(type) {
535 // NewLDAPBoolean returns a RFC 4511-compliant Boolean packet.
536 func NewLDAPBoolean(classType Class, tagType Type, tag Tag, value bool, description string) *Packet {
537 intValue := int64(0)
538
539 if value {
540 intValue = 255
541 }
542
543 p := Encode(classType, tagType, tag, nil, description)
544
545 p.Value = value
546 p.Data.Write(encodeInteger(intValue))
547
548 return p
549 }
550
551 func NewInteger(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
552 p := Encode(classType, tagType, tag, nil, description)
553
554 p.Value = value
555 switch v := value.(type) {
467556 case int:
468557 p.Data.Write(encodeInteger(int64(v)))
469558 case uint:
493582 return p
494583 }
495584
496 func NewString(ClassType Class, TagType Type, Tag Tag, Value, Description string) *Packet {
497 p := Encode(ClassType, TagType, Tag, nil, Description)
498
499 p.Value = Value
500 p.Data.Write([]byte(Value))
501
502 return p
503 }
585 func NewString(classType Class, tagType Type, tag Tag, value, description string) *Packet {
586 p := Encode(classType, tagType, tag, nil, description)
587
588 p.Value = value
589 p.Data.Write([]byte(value))
590
591 return p
592 }
593
594 func NewGeneralizedTime(classType Class, tagType Type, tag Tag, value time.Time, description string) *Packet {
595 p := Encode(classType, tagType, tag, nil, description)
596 var s string
597 if value.Nanosecond() != 0 {
598 s = value.Format(`20060102150405.000000000Z`)
599 } else {
600 s = value.Format(`20060102150405Z`)
601 }
602 p.Value = s
603 p.Data.Write([]byte(s))
604 return p
605 }
606
607 func NewReal(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
608 p := Encode(classType, tagType, tag, nil, description)
609
610 switch v := value.(type) {
611 case float64:
612 p.Data.Write(encodeFloat(v))
613 case float32:
614 p.Data.Write(encodeFloat(float64(v)))
615 default:
616 panic(fmt.Sprintf("Invalid type %T, expected float{64|32}", v))
617 }
618 return p
619 }
11
22 import (
33 "bytes"
4 "io"
45 "math"
5
6 "io"
76 "testing"
87 )
98
109 func TestEncodeDecodeInteger(t *testing.T) {
1110 for _, v := range []int64{0, 10, 128, 1024, math.MaxInt64, -1, -100, -128, -1024, math.MinInt64} {
1211 enc := encodeInteger(v)
13 dec, err := parseInt64(enc)
12 dec, err := ParseInt64(enc)
1413 if err != nil {
1514 t.Fatalf("Error decoding %d : %s", v, err)
1615 }
1716 if v != dec {
18 t.Error("TestEncodeDecodeInteger failed for %d (got %d)", v, dec)
17 t.Errorf("TestEncodeDecodeInteger failed for %d (got %d)", v, dec)
1918 }
20
2119 }
2220 }
2321
2422 func TestBoolean(t *testing.T) {
25 var value bool = true
26
27 packet := NewBoolean(ClassUniversal, TypePrimitive, TagBoolean, value, "first Packet, True")
23 packet := NewBoolean(ClassUniversal, TypePrimitive, TagBoolean, true, "first Packet, True")
2824
2925 newBoolean, ok := packet.Value.(bool)
30 if !ok || newBoolean != value {
26 if !ok || newBoolean != true {
3127 t.Error("error during creating packet")
3228 }
3329
3632 newPacket := DecodePacket(encodedPacket)
3733
3834 newBoolean, ok = newPacket.Value.(bool)
39 if !ok || newBoolean != value {
35 if !ok || newBoolean != true {
4036 t.Error("error during decoding packet")
4137 }
38 }
4239
40 func TestLDAPBoolean(t *testing.T) {
41 packet := NewLDAPBoolean(ClassUniversal, TypePrimitive, TagBoolean, true, "first Packet, True")
42
43 newBoolean, ok := packet.Value.(bool)
44 if !ok || newBoolean != true {
45 t.Error("error during creating packet")
46 }
47
48 encodedPacket := packet.Bytes()
49
50 newPacket := DecodePacket(encodedPacket)
51
52 newBoolean, ok = newPacket.Value.(bool)
53 if !ok || newBoolean != true {
54 t.Error("error during decoding packet")
55 }
4356 }
4457
4558 func TestInteger(t *testing.T) {
6073
6174 {
6275 newInteger, ok := newPacket.Value.(int64)
63 if !ok || int64(newInteger) != value {
76 if !ok || newInteger != value {
6477 t.Error("error decoding packet")
6578 }
6679 }
6780 }
6881
6982 func TestString(t *testing.T) {
70 var value string = "Hic sunt dracones"
83 var value = "Hic sunt dracones"
7184
7285 packet := NewString(ClassUniversal, TypePrimitive, TagOctetString, value, "String")
7386
8497 if !ok || newValue != value {
8598 t.Error("error during decoding packet")
8699 }
87
88100 }
89101
90102 func TestSequenceAndAppendChild(t *testing.T) {
91
92103 values := []string{
93104 "HIC SVNT LEONES",
94105 "Iñtërnâtiônàlizætiøn",
120131
121132 func TestReadPacket(t *testing.T) {
122133 packet := NewString(ClassUniversal, TypePrimitive, TagOctetString, "Ad impossibilia nemo tenetur", "string")
123 var buffer io.ReadWriter
124 buffer = new(bytes.Buffer)
134 var buffer io.ReadWriter = new(bytes.Buffer)
125135
126 buffer.Write(packet.Bytes())
136 if _, err := buffer.Write(packet.Bytes()); err != nil {
137 t.Error("error writing packet", err)
138 }
127139
128140 newPacket, err := ReadPacket(buffer)
129141 if err != nil {
152164 }
153165
154166 for _, d := range data {
155 if b := NewInteger(ClassUniversal, TypePrimitive, TagInteger, int64(d.v), "").Bytes(); !bytes.Equal(d.e, b) {
167 if b := NewInteger(ClassUniversal, TypePrimitive, TagInteger, d.v, "").Bytes(); !bytes.Equal(d.e, b) {
156168 t.Errorf("Wrong binary generated for %d : got % X, expected % X", d.v, b, d.e)
157169 }
158170 }
55
66 var j int
77 for ; n > 0; n-- {
8 out[j] = (byte(i >> uint((n-1)*8)))
8 out[j] = byte(i >> uint((n-1)*8))
99 j++
1010 }
1111
0 package ber
1
2 import (
3 "bytes"
4 "errors"
5 "fmt"
6 "strconv"
7 "time"
8 )
9
10 // ErrInvalidTimeFormat is returned when the generalizedTime string was not correct.
11 var ErrInvalidTimeFormat = errors.New("invalid time format")
12
13 var zeroTime = time.Time{}
14
15 // ParseGeneralizedTime parses a string value and if it conforms to
16 // GeneralizedTime[^0] format, will return a time.Time for that value.
17 //
18 // [^0]: https://www.itu.int/rec/T-REC-X.690-201508-I/en Section 11.7
19 func ParseGeneralizedTime(v []byte) (time.Time, error) {
20 var format string
21 var fract time.Duration
22
23 str := []byte(DecodeString(v))
24 tzIndex := bytes.IndexAny(str, "Z+-")
25 if tzIndex < 0 {
26 return zeroTime, ErrInvalidTimeFormat
27 }
28
29 dot := bytes.IndexAny(str, ".,")
30 switch dot {
31 case -1:
32 switch tzIndex {
33 case 10:
34 format = `2006010215Z`
35 case 12:
36 format = `200601021504Z`
37 case 14:
38 format = `20060102150405Z`
39 default:
40 return zeroTime, ErrInvalidTimeFormat
41 }
42
43 case 10, 12:
44 if tzIndex < dot {
45 return zeroTime, ErrInvalidTimeFormat
46 }
47 // a "," is also allowed, but would not be parsed by time.Parse():
48 str[dot] = '.'
49
50 // If <minute> is omitted, then <fraction> represents a fraction of an
51 // hour; otherwise, if <second> and <leap-second> are omitted, then
52 // <fraction> represents a fraction of a minute; otherwise, <fraction>
53 // represents a fraction of a second.
54
55 // parse as float from dot to timezone
56 f, err := strconv.ParseFloat(string(str[dot:tzIndex]), 64)
57 if err != nil {
58 return zeroTime, fmt.Errorf("failed to parse float: %s", err)
59 }
60 // ...and strip that part
61 str = append(str[:dot], str[tzIndex:]...)
62 tzIndex = dot
63
64 if dot == 10 {
65 fract = time.Duration(int64(f * float64(time.Hour)))
66 format = `2006010215Z`
67 } else {
68 fract = time.Duration(int64(f * float64(time.Minute)))
69 format = `200601021504Z`
70 }
71
72 case 14:
73 if tzIndex < dot {
74 return zeroTime, ErrInvalidTimeFormat
75 }
76 str[dot] = '.'
77 // no need for fractional seconds, time.Parse() handles that
78 format = `20060102150405Z`
79
80 default:
81 return zeroTime, ErrInvalidTimeFormat
82 }
83
84 l := len(str)
85 switch l - tzIndex {
86 case 1:
87 if str[l-1] != 'Z' {
88 return zeroTime, ErrInvalidTimeFormat
89 }
90 case 3:
91 format += `0700`
92 str = append(str, []byte("00")...)
93 case 5:
94 format += `0700`
95 default:
96 return zeroTime, ErrInvalidTimeFormat
97 }
98
99 t, err := time.Parse(format, string(str))
100 if err != nil {
101 return zeroTime, fmt.Errorf("%s: %s", ErrInvalidTimeFormat, err)
102 }
103 return t.Add(fract), nil
104 }
0 package ber
1
2 import (
3 "testing"
4 "time"
5 )
6
7 func TestParseGeneralizedTime(t *testing.T) {
8 for _, test := range []struct {
9 str string
10 wanted time.Time
11 err error
12 }{
13 {
14 "20170222190527Z",
15 time.Date(2017, time.Month(2), 22, 19, 05, 27, 0, time.UTC),
16 nil,
17 },
18 {
19 "201702221905Z",
20 time.Date(2017, time.Month(2), 22, 19, 05, 0, 0, time.UTC),
21 nil,
22 },
23 {
24 "2017022219Z",
25 time.Date(2017, time.Month(2), 22, 19, 0, 0, 0, time.UTC),
26 nil,
27 },
28 {
29 "2017022219.25Z",
30 time.Date(2017, time.Month(2), 22, 19, 15, 0, 0, time.UTC),
31 nil,
32 },
33 {
34 "201702221905.25Z",
35 time.Date(2017, time.Month(2), 22, 19, 5, 15, 0, time.UTC),
36 nil,
37 },
38 {
39 "20170222190525-0100",
40 time.Date(2017, time.Month(2), 22, 19, 5, 25, 0, time.FixedZone("", -3600)),
41 nil,
42 },
43 {
44 "20170222190525+0100",
45 time.Date(2017, time.Month(2), 22, 19, 5, 25, 0, time.FixedZone("", 3600)),
46 nil,
47 },
48 {
49 "20170222190525+01",
50 time.Date(2017, time.Month(2), 22, 19, 5, 25, 0, time.FixedZone("", 3600)),
51 nil,
52 },
53 {
54 "20170222190527.123Z",
55 time.Date(2017, time.Month(2), 22, 19, 05, 27, 123*1000*1000, time.UTC),
56 nil,
57 },
58 {
59 "20170222190527,123Z",
60 time.Date(2017, time.Month(2), 22, 19, 05, 27, 123*1000*1000, time.UTC),
61 nil,
62 },
63 {
64 "2017022219-0100",
65 time.Date(2017, time.Month(2), 22, 19, 0, 0, 0, time.FixedZone("", -3600)),
66 nil,
67 },
68 } {
69 genTime, err := ParseGeneralizedTime([]byte(test.str))
70 if err != nil {
71 if test.err != nil {
72 if err != test.err {
73 t.Errorf("unexpected error in %s: %s", test.str, err)
74 }
75 } else {
76 t.Errorf("test %s failed with error: %s", test.str, err)
77 }
78 } else {
79 if !genTime.Equal(test.wanted) {
80 t.Errorf("test got unexpected result: wanted=%s, got=%s", test.wanted, genTime)
81 }
82 }
83 }
84 }
0 module github.com/go-asn1-ber/asn1-ber
1
2 go 1.13
11
22 import (
33 "errors"
4 "fmt"
45 "io"
56 )
67
78 func readHeader(reader io.Reader) (identifier Identifier, length int, read int, err error) {
8 if i, c, err := readIdentifier(reader); err != nil {
9 var (
10 c, l int
11 i Identifier
12 )
13
14 if i, c, err = readIdentifier(reader); err != nil {
915 return Identifier{}, 0, read, err
10 } else {
11 identifier = i
12 read += c
1316 }
17 identifier = i
18 read += c
1419
15 if l, c, err := readLength(reader); err != nil {
20 if l, c, err = readLength(reader); err != nil {
1621 return Identifier{}, 0, read, err
17 } else {
18 length = l
19 read += c
2022 }
23 length = l
24 read += c
2125
2226 // Validate length type with identifier (x.600, 8.1.3.2.a)
2327 if length == LengthIndefinite && identifier.TagType == TypePrimitive {
2428 return Identifier{}, 0, read, errors.New("indefinite length used with primitive type")
2529 }
2630
31 if length < LengthIndefinite {
32 err = fmt.Errorf("length cannot be less than %d", LengthIndefinite)
33 return
34 }
35
2736 return identifier, length, read, nil
2837 }
66 )
77
88 func TestReadHeader(t *testing.T) {
9 testcases := map[string]struct {
9 testCases := map[string]struct {
1010 Data []byte
1111 ExpectedIdentifier Identifier
1212 ExpectedLength int
8383 },
8484 }
8585
86 for k, tc := range testcases {
86 for k, tc := range testCases {
8787 reader := bytes.NewBuffer(tc.Data)
8888 identifier, length, read, err := readHeader(reader)
8989
33 "errors"
44 "fmt"
55 "io"
6 "math"
76 )
87
98 func readIdentifier(reader io.Reader) (Identifier, int, error) {
7978
8079 tag := identifier.Tag
8180
82 highBit := uint(63)
83 for {
84 if tag&(1<<highBit) != 0 {
85 break
86 }
87 highBit--
88 }
89
90 tagBytes := int(math.Ceil(float64(highBit) / 7.0))
91 for i := tagBytes - 1; i >= 0; i-- {
92 offset := uint(i) * 7
93 mask := Tag(0x7f) << offset
94 tagByte := (tag & mask) >> offset
95 if i != 0 {
96 tagByte |= 0x80
97 }
98 b = append(b, byte(tagByte))
99 }
81 b = append(b, encodeHighTag(tag)...)
10082 }
10183 return b
10284 }
85
86 func encodeHighTag(tag Tag) []byte {
87 // set cap=4 to hopefully avoid additional allocations
88 b := make([]byte, 0, 4)
89 for tag != 0 {
90 // t := last 7 bits of tag (HighTagValueBitmask = 0x7F)
91 t := tag & HighTagValueBitmask
92
93 // right shift tag 7 to remove what was just pulled off
94 tag >>= 7
95
96 // if b already has entries this entry needs a continuation bit (0x80)
97 if len(b) != 0 {
98 t |= HighTagContinueBitmask
99 }
100
101 b = append(b, byte(t))
102 }
103 // reverse
104 // since bits were pulled off 'tag' small to high the byte slice is in reverse order.
105 // example: tag = 0xFF results in {0x7F, 0x01 + 0x80 (continuation bit)}
106 // this needs to be reversed into 0x81 0x7F
107 for i, j := 0, len(b)-1; i < len(b)/2; i++ {
108 b[i], b[j-i] = b[j-i], b[i]
109 }
110 return b
111 }
77 )
88
99 func TestReadIdentifier(t *testing.T) {
10 testcases := map[string]struct {
10 testCases := map[string]struct {
1111 Data []byte
1212
1313 ExpectedIdentifier Identifier
180180 },
181181 }
182182
183 for k, tc := range testcases {
183 for k, tc := range testCases {
184184 reader := bytes.NewBuffer(tc.Data)
185185 identifier, read, err := readIdentifier(reader)
186186
227227 }
228228
229229 func TestEncodeIdentifier(t *testing.T) {
230 testcases := map[string]struct {
230 testCases := map[string]struct {
231231 Identifier Identifier
232232 ExpectedBytes []byte
233233 }{
334334 },
335335 }
336336
337 for k, tc := range testcases {
337 for k, tc := range testCases {
338338 b := encodeIdentifier(tc.Identifier)
339 if bytes.Compare(tc.ExpectedBytes, b) != 0 {
339 if !bytes.Equal(tc.ExpectedBytes, b) {
340340 t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, tc.ExpectedBytes, b)
341341 }
342342 }
343343 }
344
345 func TestEncodeHighTag(t *testing.T) {
346 cases := []struct {
347 tag Tag
348 want []byte
349 }{
350 {134, []byte{0x80 + 0x01, 0x06}},
351 {123456, []byte{0x80 + 0x07, 0x80 + 0x44, 0x40}},
352 {0xFF, []byte{0x81, 0x7F}},
353 }
354
355 for _, c := range cases {
356 got := encodeHighTag(c.tag)
357
358 if !bytes.Equal(c.want, got) {
359 t.Errorf("tag: %d want: %#v got: %#v", c.tag, c.want, got)
360 }
361 }
362 }
7070 }
7171
7272 func encodeLength(length int) []byte {
73 length_bytes := encodeUnsignedInteger(uint64(length))
74 if length > 127 || len(length_bytes) > 1 {
75 longFormBytes := []byte{(LengthLongFormBitmask | byte(len(length_bytes)))}
76 longFormBytes = append(longFormBytes, length_bytes...)
77 length_bytes = longFormBytes
73 lengthBytes := encodeUnsignedInteger(uint64(length))
74 if length > 127 || len(lengthBytes) > 1 {
75 longFormBytes := []byte{LengthLongFormBitmask | byte(len(lengthBytes))}
76 longFormBytes = append(longFormBytes, lengthBytes...)
77 lengthBytes = longFormBytes
7878 }
79 return length_bytes
79 return lengthBytes
8080 }
77 )
88
99 func TestReadLength(t *testing.T) {
10 testcases := map[string]struct {
10 testCases := map[string]struct {
1111 Data []byte
1212
1313 ExpectedLength int64
9696 },
9797 }
9898
99 for k, tc := range testcases {
99 for k, tc := range testCases {
100100 // Skip tests requiring 64-bit integers on platforms that don't support them
101101 if tc.ExpectedLength != int64(int(tc.ExpectedLength)) {
102102 continue
127127 }
128128
129129 func TestEncodeLength(t *testing.T) {
130 testcases := map[string]struct {
130 testCases := map[string]struct {
131131 Length int64
132132 ExpectedBytes []byte
133133 }{
176176 },
177177 }
178178
179 for k, tc := range testcases {
179 for k, tc := range testCases {
180180 // Skip tests requiring 64-bit integers on platforms that don't support them
181181 if tc.Length != int64(int(tc.Length)) {
182182 continue
183183 }
184184
185185 b := encodeLength(int(tc.Length))
186 if bytes.Compare(tc.ExpectedBytes, b) != 0 {
186 if !bytes.Equal(tc.ExpectedBytes, b) {
187187 t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, tc.ExpectedBytes, b)
188188 }
189189 }
0 package ber
1
2 import (
3 "bytes"
4 "errors"
5 "fmt"
6 "math"
7 "strconv"
8 "strings"
9 )
10
11 func encodeFloat(v float64) []byte {
12 switch {
13 case math.IsInf(v, 1):
14 return []byte{0x40}
15 case math.IsInf(v, -1):
16 return []byte{0x41}
17 case math.IsNaN(v):
18 return []byte{0x42}
19 case v == 0.0:
20 if math.Signbit(v) {
21 return []byte{0x43}
22 }
23 return []byte{}
24 default:
25 // we take the easy part ;-)
26 value := []byte(strconv.FormatFloat(v, 'G', -1, 64))
27 var ret []byte
28 if bytes.Contains(value, []byte{'E'}) {
29 ret = []byte{0x03}
30 } else {
31 ret = []byte{0x02}
32 }
33 ret = append(ret, value...)
34 return ret
35 }
36 }
37
38 func ParseReal(v []byte) (val float64, err error) {
39 if len(v) == 0 {
40 return 0.0, nil
41 }
42 switch {
43 case v[0]&0x80 == 0x80:
44 val, err = parseBinaryFloat(v)
45 case v[0]&0xC0 == 0x40:
46 val, err = parseSpecialFloat(v)
47 case v[0]&0xC0 == 0x0:
48 val, err = parseDecimalFloat(v)
49 default:
50 return 0.0, fmt.Errorf("invalid info block")
51 }
52 if err != nil {
53 return 0.0, err
54 }
55
56 if val == 0.0 && !math.Signbit(val) {
57 return 0.0, errors.New("REAL value +0 must be encoded with zero-length value block")
58 }
59 return val, nil
60 }
61
62 func parseBinaryFloat(v []byte) (float64, error) {
63 var info byte
64 var buf []byte
65
66 info, v = v[0], v[1:]
67
68 var base int
69 switch info & 0x30 {
70 case 0x00:
71 base = 2
72 case 0x10:
73 base = 8
74 case 0x20:
75 base = 16
76 case 0x30:
77 return 0.0, errors.New("bits 6 and 5 of information octet for REAL are equal to 11")
78 }
79
80 scale := uint((info & 0x0c) >> 2)
81
82 var expLen int
83 switch info & 0x03 {
84 case 0x00:
85 expLen = 1
86 case 0x01:
87 expLen = 2
88 case 0x02:
89 expLen = 3
90 case 0x03:
91 expLen = int(v[0])
92 if expLen > 8 {
93 return 0.0, errors.New("too big value of exponent")
94 }
95 v = v[1:]
96 }
97 buf, v = v[:expLen], v[expLen:]
98 exponent, err := ParseInt64(buf)
99 if err != nil {
100 return 0.0, err
101 }
102
103 if len(v) > 8 {
104 return 0.0, errors.New("too big value of mantissa")
105 }
106
107 mant, err := ParseInt64(v)
108 if err != nil {
109 return 0.0, err
110 }
111 mantissa := mant << scale
112
113 if info&0x40 == 0x40 {
114 mantissa = -mantissa
115 }
116
117 return float64(mantissa) * math.Pow(float64(base), float64(exponent)), nil
118 }
119
120 func parseDecimalFloat(v []byte) (val float64, err error) {
121 switch v[0] & 0x3F {
122 case 0x01: // NR form 1
123 var iVal int64
124 iVal, err = strconv.ParseInt(strings.TrimLeft(string(v[1:]), " "), 10, 64)
125 val = float64(iVal)
126 case 0x02, 0x03: // NR form 2, 3
127 val, err = strconv.ParseFloat(strings.Replace(strings.TrimLeft(string(v[1:]), " "), ",", ".", -1), 64)
128 default:
129 err = errors.New("incorrect NR form")
130 }
131 if err != nil {
132 return 0.0, err
133 }
134
135 if val == 0.0 && math.Signbit(val) {
136 return 0.0, errors.New("REAL value -0 must be encoded as a special value")
137 }
138 return val, nil
139 }
140
141 func parseSpecialFloat(v []byte) (float64, error) {
142 if len(v) != 1 {
143 return 0.0, errors.New(`encoding of "special value" must not contain exponent and mantissa`)
144 }
145 switch v[0] {
146 case 0x40:
147 return math.Inf(1), nil
148 case 0x41:
149 return math.Inf(-1), nil
150 case 0x42:
151 return math.NaN(), nil
152 case 0x43:
153 return math.Copysign(0, -1), nil
154 }
155 return 0.0, errors.New(`encoding of "special value" not from ASN.1 standard`)
156 }
0 package ber
1
2 import (
3 "math"
4 "testing"
5 )
6
7 var negativeZero = math.Copysign(0, -1)
8
9 func TestRealEncoding(t *testing.T) {
10 for _, value := range []float64{
11 0.15625,
12 -0.15625,
13 math.Inf(1),
14 math.Inf(-1),
15 math.NaN(),
16 negativeZero,
17 0.0,
18 } {
19 enc := encodeFloat(value)
20 dec, err := ParseReal(enc)
21 if err != nil {
22 t.Errorf("Failed to decode %f (%v): %s", value, enc, err)
23 }
24 if dec != value {
25 if !(math.IsNaN(dec) && math.IsNaN(value)) {
26 t.Errorf("decoded value != orig: %f <=> %f", value, dec)
27 }
28 }
29 }
30 }
0 package ber
1
2 import (
3 "testing"
4 )
5
6 func TestIA5String(t *testing.T) {
7 for _, test := range []struct {
8 value string
9 expectedErr string
10 }{
11 {"asdfgh", ""},
12 {"asdfgå", "invalid character for IA5String at pos 5: å"},
13 } {
14 pkt := NewString(ClassUniversal, TypePrimitive, TagIA5String, test.value, test.value)
15 dec, err := DecodePacketErr(pkt.Bytes())
16 if err == nil {
17 if test.expectedErr != "" {
18 t.Errorf("got unexpected error for `%s`: %s", test.value, err)
19 }
20 if dec.Value.(string) != test.value {
21 t.Errorf("did not get back original value: %s <=> %s", dec.Value.(string), test.value)
22 }
23 } else if err.Error() != test.expectedErr {
24 t.Errorf("got unexpected error for `%s`: %s", test.value, err)
25 }
26 }
27 }
28
29 func TestPrintableString(t *testing.T) {
30 for _, test := range []struct {
31 value string
32 expectedErr string
33 }{
34 {"asdfgh", ""},
35 {"asdfgå", "invalid character in position 5"},
36 } {
37 pkt := NewString(ClassUniversal, TypePrimitive, TagPrintableString, test.value, test.value)
38 dec, err := DecodePacketErr(pkt.Bytes())
39 if err == nil {
40 if test.expectedErr != "" {
41 t.Errorf("got unexpected error for `%s`: %s", test.value, err)
42 }
43 if dec.Value.(string) != test.value {
44 t.Errorf("did not get back original value: %s <=> %s", dec.Value.(string), test.value)
45 }
46 } else if err.Error() != test.expectedErr {
47 t.Errorf("got unexpected error for `%s`: %s", test.value, err)
48 }
49 }
50 }
51
52 func TestUTF8String(t *testing.T) {
53 for _, test := range []struct {
54 value string
55 expectedErr string
56 }{
57 {"åäöüß", ""},
58 {"asdfg\xFF", "invalid UTF-8 string"},
59 } {
60 pkt := NewString(ClassUniversal, TypePrimitive, TagUTF8String, test.value, test.value)
61 dec, err := DecodePacketErr(pkt.Bytes())
62 if err == nil {
63 if test.expectedErr != "" {
64 t.Errorf("got unexpected error for `%s`: %s", test.value, err)
65 }
66 if dec.Value.(string) != test.value {
67 t.Errorf("did not get back original value: %s <=> %s", dec.Value.(string), test.value)
68 }
69 } else if err.Error() != test.expectedErr {
70 t.Errorf("got unexpected error for `%s`: %s", test.value, err)
71 }
72 }
73 }
11
22 import (
33 "bytes"
4 "fmt"
45 "io"
56 "io/ioutil"
7 "math"
68 "testing"
79 )
810
1012
1113 // Tests from http://www.strozhevsky.com/free_docs/free_asn1_testsuite_descr.pdf
1214 // Source files and descriptions at http://www.strozhevsky.com/free_docs/TEST_SUITE.zip
13 var testcases = []struct {
15 var testCases = []struct {
1416 // File contains the path to the BER-encoded file
1517 File string
1618 // Error indicates whether a decoding error is expected
2729 {File: "tests/tc4.ber", Error: "invalid length byte 0xff"},
2830 {File: "tests/tc5.ber", Error: "", AbnormalEncoding: true},
2931 // Real numbers (some expected failures are disabled until support is added)
30 {File: "tests/tc6.ber", Error: ""}, // Error: "REAL value +0 must be encoded with zero-length value block"},
31 {File: "tests/tc7.ber", Error: ""}, // Error: "REAL value -0 must be encoded as a special value"},
32 {File: "tests/tc8.ber", Error: ""},
33 {File: "tests/tc9.ber", Error: ""}, // Error: "Bits 6 and 5 of information octet for REAL are equal to 11"
32 {File: "tests/tc6.ber", Error: "REAL value +0 must be encoded with zero-length value block"},
33 {File: "tests/tc7.ber", Error: "REAL value -0 must be encoded as a special value"},
34 {File: "tests/tc8.ber", Error: `encoding of "special value" must not contain exponent and mantissa`},
35 {File: "tests/tc9.ber", Error: "bits 6 and 5 of information octet for REAL are equal to 11"},
3436 {File: "tests/tc10.ber", Error: ""},
35 {File: "tests/tc11.ber", Error: ""}, // Error: "Incorrect NR form"
36 {File: "tests/tc12.ber", Error: ""}, // Error: "Encoding of "special value" not from ASN.1 standard"
37 {File: "tests/tc11.ber", Error: "incorrect NR form"},
38 {File: "tests/tc12.ber", Error: `encoding of "special value" not from ASN.1 standard`},
3739 {File: "tests/tc13.ber", Error: errEOF},
3840 {File: "tests/tc14.ber", Error: errEOF},
39 {File: "tests/tc15.ber", Error: ""}, // Error: "Too big value of exponent"
40 {File: "tests/tc16.ber", Error: ""}, // Error: "Too big value of mantissa"
41 {File: "tests/tc17.ber", Error: ""}, // Error: "Too big values for exponent and mantissa + using of "scaling factor" value"
41 {File: "tests/tc15.ber", Error: "too big value of exponent"},
42 {File: "tests/tc16.ber", Error: "too big value of mantissa"},
43 {File: "tests/tc17.ber", Error: "too big value of exponent"}, // Error: "Too big values for exponent and mantissa + using of "scaling factor" value"
4244 // Integers
4345 {File: "tests/tc18.ber", Error: ""},
4446 {File: "tests/tc19.ber", Error: errEOF},
5860 {File: "tests/tc30.ber", Error: ""},
5961 {File: "tests/tc31.ber", Error: errEOF},
6062 {File: "tests/tc32.ber", Error: ""},
61 // Bitstring (some expected failures are disabled until support is added)
63 // Bit string (some expected failures are disabled until support is added)
6264 {File: "tests/tc33.ber", Error: ""}, // Error: "Too big value for "unused bits""
6365 {File: "tests/tc34.ber", Error: errEOF},
6466 {File: "tests/tc35.ber", Error: "", IndefiniteEncoding: true}, // Error: "Using of different from BIT STRING types as internal types for constructive encoding"
7375 {File: "tests/tc43.ber", Error: errEOF},
7476 {File: "tests/tc44.ber", Error: ""},
7577 {File: "tests/tc45.ber", Error: ""},
76 // Bitstring
78 // Bit string
7779 {File: "tests/tc46.ber", Error: "indefinite length used with primitive type"},
7880 {File: "tests/tc47.ber", Error: "eoc child not allowed with definite length"},
7981 {File: "tests/tc48.ber", Error: "", IndefiniteEncoding: true}, // Error: "Using of more than 7 "unused bits" in BIT STRING with constrictive encoding form"
82 {File: "tests/tc49.ber", Error: ""},
83 {File: "tests/tc50.ber", Error: is64bit("length cannot be less than -1", "long-form length overflow")},
84 {File: "tests/tc51.ber", Error: is64bit(fmt.Sprintf("length 206966894640 greater than maximum %v", MaxPacketLengthBytes), "long-form length overflow")},
85 }
86
87 func is64bit(a, b string) string {
88 maxInt64 := int64(math.MaxInt64)
89 length := int(maxInt64)
90 if int64(length) != maxInt64 {
91 return b
92 }
93 return a
8094 }
8195
8296 func TestSuiteDecodePacket(t *testing.T) {
8397 // Debug = true
84 for _, tc := range testcases {
98 for _, tc := range testCases {
8599 file := tc.File
86100
87101 dataIn, err := ioutil.ReadFile(file)
113127 }
114128 } else if !bytes.Equal(dataOut, dataIn) {
115129 // Make sure the serialized data matches the source
116 t.Errorf("%s: data should be the same", file)
130 t.Errorf("%s: data should be the same\nwant: %#v\ngot: %#v", file, dataIn, dataOut)
117131 }
118132
119133 packet, err = DecodePacketErr(dataOut)
125139 // Make sure the re-serialized data matches our original serialization
126140 dataOut2 := packet.Bytes()
127141 if !bytes.Equal(dataOut, dataOut2) {
128 t.Errorf("%s: data should be the same", file)
142 t.Errorf("%s: data should be the same\nwant: %#v\ngot: %#v", file, dataOut, dataOut2)
129143 }
130144 }
131145 }
132146
133147 func TestSuiteReadPacket(t *testing.T) {
134 for _, tc := range testcases {
148 for _, tc := range testCases {
135149 file := tc.File
136150
137151 dataIn, err := ioutil.ReadFile(file)
163177 }
164178 } else if !bytes.Equal(dataOut, dataIn) {
165179 // Make sure the serialized data matches the source
166 t.Errorf("%s: data should be the same", file)
180 t.Errorf("%s: data should be the same\nwant: %#v\ngot: %#v", file, dataIn, dataOut)
167181 }
168182
169183 packet, err = DecodePacketErr(dataOut)
175189 // Make sure the re-serialized data matches our original serialization
176190 dataOut2 := packet.Bytes()
177191 if !bytes.Equal(dataOut, dataOut2) {
178 t.Errorf("%s: data should be the same", file)
192 t.Errorf("%s: data should be the same\nwant: %#v\ngot: %#v", file, dataOut, dataOut2)
179193 }
180194 }
181195 }
Binary diff not shown
0 ˆ›0000000
0 …00000
22 import "io"
33
44 func readByte(reader io.Reader) (byte, error) {
5 bytes := make([]byte, 1, 1)
5 bytes := make([]byte, 1)
66 _, err := io.ReadFull(reader, bytes)
77 if err != nil {
88 if err == io.EOF {