OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // The asn1 package implements parsing of DER-encoded ASN.1 data structures, | 5 // The asn1 package implements parsing of DER-encoded ASN.1 data structures, |
6 // as defined in ITU-T Rec X.690. | 6 // as defined in ITU-T Rec X.690. |
7 // | 7 // |
8 // See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' | 8 // See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' |
9 // http://luca.ntop.org/Teaching/Appunti/asn1.html. | 9 // http://luca.ntop.org/Teaching/Appunti/asn1.html. |
10 package asn1 | 10 package asn1 |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 return; | 342 return; |
343 } | 343 } |
344 | 344 |
345 // A RawValue represents an undecoded ASN.1 object. | 345 // A RawValue represents an undecoded ASN.1 object. |
346 type RawValue struct { | 346 type RawValue struct { |
347 Class, Tag int; | 347 Class, Tag int; |
348 IsCompound bool; | 348 IsCompound bool; |
349 Bytes []byte; | 349 Bytes []byte; |
350 } | 350 } |
351 | 351 |
| 352 // RawContent is used to signal that the undecoded, DER data needs to be |
| 353 // preserved for a struct. To use it, the first field of the struct must have |
| 354 // this type. It's an error for any of the other fields to have this type. |
| 355 type RawContent []byte |
| 356 |
352 // Tagging | 357 // Tagging |
353 | 358 |
354 // parseTagAndLength parses an ASN.1 tag and length pair from the given offset | 359 // parseTagAndLength parses an ASN.1 tag and length pair from the given offset |
355 // into a byte array. It returns the parsed data and the new offset. SET and | 360 // into a byte array. It returns the parsed data and the new offset. SET and |
356 // SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we | 361 // SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we |
357 // don't distinguish between ordered and unordered objects in this code. | 362 // don't distinguish between ordered and unordered objects in this code. |
358 func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
nt, err os.Error) { | 363 func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
nt, err os.Error) { |
359 offset = initOffset; | 364 offset = initOffset; |
360 b := bytes[offset]; | 365 b := bytes[offset]; |
361 offset++; | 366 offset++; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 } | 458 } |
454 } | 459 } |
455 return; | 460 return; |
456 } | 461 } |
457 | 462 |
458 var ( | 463 var ( |
459 bitStringType = reflect.Typeof(BitString{}); | 464 bitStringType = reflect.Typeof(BitString{}); |
460 objectIdentifierType = reflect.Typeof(ObjectIdentifier{}); | 465 objectIdentifierType = reflect.Typeof(ObjectIdentifier{}); |
461 timeType = reflect.Typeof(&time.Time{}); | 466 timeType = reflect.Typeof(&time.Time{}); |
462 rawValueType = reflect.Typeof(RawValue{}); | 467 rawValueType = reflect.Typeof(RawValue{}); |
| 468 rawContentsType = reflect.Typeof(RawContent(nil)); |
463 ) | 469 ) |
464 | 470 |
465 // invalidLength returns true iff offset + length > sliceLength, or if the | 471 // invalidLength returns true iff offset + length > sliceLength, or if the |
466 // addition would overflow. | 472 // addition would overflow. |
467 func invalidLength(offset, length, sliceLength int) bool { | 473 func invalidLength(offset, length, sliceLength int) bool { |
468 return offset+length < offset || offset+length > sliceLength | 474 return offset+length < offset || offset+length > sliceLength |
469 } | 475 } |
470 | 476 |
471 // parseField is the main parsing function. Given a byte array and an offset | 477 // parseField is the main parsing function. Given a byte array and an offset |
472 // into the array, it will try to parse a suitable ASN.1 value out and store it | 478 // into the array, it will try to parse a suitable ASN.1 value out and store it |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 expectedTag = *params.tag; | 593 expectedTag = *params.tag; |
588 } | 594 } |
589 | 595 |
590 // We have unwrapped any explicit tagging at this point. | 596 // We have unwrapped any explicit tagging at this point. |
591 if t.class != expectedClass || t.tag != expectedTag || t.isCompound != c
ompoundType { | 597 if t.class != expectedClass || t.tag != expectedTag || t.isCompound != c
ompoundType { |
592 // Tags don't match. Again, it could be an optional element. | 598 // Tags don't match. Again, it could be an optional element. |
593 ok := setDefaultValue(v, params); | 599 ok := setDefaultValue(v, params); |
594 if ok { | 600 if ok { |
595 offset = initOffset | 601 offset = initOffset |
596 } else { | 602 } else { |
597 » » » err = StructuralError{fmt.Sprintf("tags don't match (%d
vs %+v) %+v %s %#v", expectedTag, t, params, fieldType.Name(), bytes[offset:len(
bytes)])} | 603 » » » err = StructuralError{fmt.Sprintf("tags don't match (%d
vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)} |
598 } | 604 } |
599 return; | 605 return; |
600 } | 606 } |
601 if invalidLength(offset, t.length, len(bytes)) { | 607 if invalidLength(offset, t.length, len(bytes)) { |
602 err = SyntaxError{"data truncated"}; | 608 err = SyntaxError{"data truncated"}; |
603 return; | 609 return; |
604 } | 610 } |
605 innerBytes := bytes[offset : offset+t.length]; | 611 innerBytes := bytes[offset : offset+t.length]; |
606 | 612 |
607 // We deal with the structures defined in this package first. | 613 // We deal with the structures defined in this package first. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 case *reflect.Int64Value: | 661 case *reflect.Int64Value: |
656 parsedInt, err1 := parseInt64(innerBytes); | 662 parsedInt, err1 := parseInt64(innerBytes); |
657 offset += t.length; | 663 offset += t.length; |
658 if err1 == nil { | 664 if err1 == nil { |
659 val.Set(parsedInt) | 665 val.Set(parsedInt) |
660 } | 666 } |
661 err = err1; | 667 err = err1; |
662 return; | 668 return; |
663 case *reflect.StructValue: | 669 case *reflect.StructValue: |
664 structType := fieldType.(*reflect.StructType); | 670 structType := fieldType.(*reflect.StructType); |
| 671 |
| 672 if structType.NumField() > 0 && |
| 673 structType.Field(0).Type == rawContentsType { |
| 674 bytes := bytes[initOffset : offset+t.length]; |
| 675 val.Field(0).SetValue(reflect.NewValue(RawContent(bytes)
)); |
| 676 } |
| 677 |
665 innerOffset := 0; | 678 innerOffset := 0; |
666 for i := 0; i < structType.NumField(); i++ { | 679 for i := 0; i < structType.NumField(); i++ { |
667 field := structType.Field(i); | 680 field := structType.Field(i); |
| 681 if i == 0 && field.Type == rawContentsType { |
| 682 continue |
| 683 } |
668 innerOffset, err = parseField(val.Field(i), innerBytes,
innerOffset, parseFieldParameters(field.Tag)); | 684 innerOffset, err = parseField(val.Field(i), innerBytes,
innerOffset, parseFieldParameters(field.Tag)); |
669 if err != nil { | 685 if err != nil { |
670 return | 686 return |
671 } | 687 } |
672 } | 688 } |
673 offset += t.length; | 689 offset += t.length; |
674 // We allow extra bytes at the end of the SEQUENCE because | 690 // We allow extra bytes at the end of the SEQUENCE because |
675 // adding elements to the end has been used in X.509 as the | 691 // adding elements to the end has been used in X.509 as the |
676 // version numbers have increased. | 692 // version numbers have increased. |
677 return; | 693 return; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 // An ASN.1 SEQUENCE or SET can be written to a struct | 772 // An ASN.1 SEQUENCE or SET can be written to a struct |
757 // if each of the elements in the sequence can be | 773 // if each of the elements in the sequence can be |
758 // written to the corresponding element in the struct. | 774 // written to the corresponding element in the struct. |
759 // | 775 // |
760 // The following tags on struct fields have special meaning to Unmarshal: | 776 // The following tags on struct fields have special meaning to Unmarshal: |
761 // | 777 // |
762 // optional marks the field as ASN.1 OPTIONAL | 778 // optional marks the field as ASN.1 OPTIONAL |
763 // [explicit] tag:x specifies the ASN.1 tag number; implies ASN.1 CO
NTEXT SPECIFIC | 779 // [explicit] tag:x specifies the ASN.1 tag number; implies ASN.1 CO
NTEXT SPECIFIC |
764 // default:x sets the default value for optional integer fiel
ds | 780 // default:x sets the default value for optional integer fiel
ds |
765 // | 781 // |
| 782 // If the type of the first field of a structure is RawContent then the raw |
| 783 // ASN1 contents of the struct will be stored in it. |
| 784 // |
766 // Other ASN.1 types are not supported; if it encounters them, | 785 // Other ASN.1 types are not supported; if it encounters them, |
767 // Unmarshal returns a parse error. | 786 // Unmarshal returns a parse error. |
768 func Unmarshal(val interface{}, b []byte) (rest []byte, err os.Error) { | 787 func Unmarshal(val interface{}, b []byte) (rest []byte, err os.Error) { |
769 v := reflect.NewValue(val).(*reflect.PtrValue).Elem(); | 788 v := reflect.NewValue(val).(*reflect.PtrValue).Elem(); |
770 offset, err := parseField(v, b, 0, fieldParameters{}); | 789 offset, err := parseField(v, b, 0, fieldParameters{}); |
771 if err != nil { | 790 if err != nil { |
772 return nil, err | 791 return nil, err |
773 } | 792 } |
774 return b[offset:len(b)], nil; | 793 return b[offset:len(b)], nil; |
775 } | 794 } |
OLD | NEW |