package message // Below code is largely inspired from the standard golang library encoding/asn // If put BEGIN / END tags in the comments to give the original library name import ( // "errors" "fmt" "math/big" // "strconv" // "time" ) // // BEGIN: encoding/asn1/common.go // // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. const ( tagBoolean = 1 tagInteger = 2 // tagBitString = 3 tagOctetString = 4 // tagOID = 6 tagEnum = 10 // tagUTF8String = 12 tagSequence = 16 tagSet = 17 // tagPrintableString = 19 // tagT61String = 20 // tagIA5String = 22 // tagUTCTime = 23 // tagGeneralizedTime = 24 tagGeneralString = 27 ) var tagNames = map[int]string{ tagBoolean: "BOOLEAN", tagInteger: "INTEGER", tagOctetString: "OCTET STRING", tagEnum: "ENUM", tagSequence: "SEQUENCE", tagSet: "SET", } const ( classUniversal = 0 classApplication = 1 classContextSpecific = 2 // classPrivate = 3 ) var classNames = map[int]string{ classUniversal: "UNIVERSAL", classApplication: "APPLICATION", classContextSpecific: "CONTEXT SPECIFIC", } const ( isCompound = true isNotCompound = false ) var compoundNames = map[bool]string{ isCompound: "COMPOUND", isNotCompound: "NOT COMPOUND", } type TagAndLength struct { Class, Tag, Length int IsCompound bool } // // END: encoding/asn1/common.go // func (t *TagAndLength) Expect(class int, tag int, isCompound bool) (err error) { err = t.ExpectClass(class) if err != nil { return LdapError{fmt.Sprintf("Expect: %s.", err)} } err = t.ExpectTag(tag) if err != nil { return LdapError{fmt.Sprintf("Expect: %s.", err)} } err = t.ExpectCompound(isCompound) if err != nil { return LdapError{fmt.Sprintf("Expect: %s.", err)} } return } func (t *TagAndLength) ExpectClass(class int) (err error) { if class != t.Class { err = SyntaxError{fmt.Sprintf("ExpectClass: wrong tag class: got %d (%s), expected %d (%s)", t.Class, classNames[t.Class], class, classNames[class])} } return } func (t *TagAndLength) ExpectTag(tag int) (err error) { if tag != t.Tag { err = SyntaxError{fmt.Sprintf("ExpectTag: wrong tag value: got %d (%s), expected %d (%s)", t.Tag, tagNames[t.Tag], tag, tagNames[tag])} } return } func (t *TagAndLength) ExpectCompound(isCompound bool) (err error) { if isCompound != t.IsCompound { err = SyntaxError{fmt.Sprintf("ExpectCompound: wrong tag compound: got %t (%s), expected %t (%s)", t.IsCompound, compoundNames[t.IsCompound], isCompound, compoundNames[isCompound])} } return } func ParseTagAndLength(bytes []byte, initOffset int) (ret TagAndLength, offset int, err error) { ret, offset, err = parseTagAndLength(bytes, initOffset) return } // // BEGIN encoding/asn1/asn1.go // // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package asn1 implements parsing of DER-encoded ASN.1 data structures, // as defined in ITU-T Rec X.690. // // See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' // http://luca.ntop.org/Teaching/Appunti/asn1.html. // package asn1 // ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc // are different encoding formats for those objects. Here, we'll be dealing // with DER, the Distinguished Encoding Rules. DER is used in X.509 because // it's fast to parse and, unlike BER, has a unique encoding for every object. // When calculating hashes over objects, it's important that the resulting // bytes be the same at both ends and DER removes this margin of error. // // ASN.1 is very complex and this package doesn't attempt to implement // everything by any means. //import ( // "fmt" // "math/big" // "reflect" // "strconv" // "time" //) // A StructuralError suggests that the ASN.1 data is valid, but the Go type // which is receiving it doesn't match. type StructuralError struct { Msg string } func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg } // A SyntaxError suggests that the ASN.1 data is invalid. type SyntaxError struct { Msg string } func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg } // We start by dealing with each of the primitive types in turn. // BOOLEAN func parseBool(bytes []byte) (ret bool, err error) { if len(bytes) > 1 { err = SyntaxError{"invalid boolean: should be encoded on one byte only"} return } else if len(bytes) == 0 { err = SyntaxError{"invalid boolean: no data to read"} } // DER demands that "If the encoding represents the boolean value TRUE, // its single contents octet shall have all eight bits set to one." // Thus only 0 and 255 are valid encoded values. switch bytes[0] { case 0: ret = false case 0xff: ret = true default: err = SyntaxError{"invalid boolean: should be 0x00 of 0xFF"} } return } func sizeBool(b bool) int { return 1 } func writeBool(bytes *Bytes, b bool) int { if b == false { return bytes.writeBytes([]byte{0x00}) } else { return bytes.writeBytes([]byte{0xff}) } } // INTEGER // parseInt64 treats the given bytes as a big-endian, signed integer and // returns the result. func parseInt64(bytes []byte) (ret int64, err error) { if len(bytes) > 8 { // We'll overflow an int64 in this case. err = StructuralError{"integer too large"} return } for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { ret <<= 8 ret |= int64(bytes[bytesRead]) } // Shift up and down in order to sign extend the result. ret <<= 64 - uint8(len(bytes))*8 ret >>= 64 - uint8(len(bytes))*8 return } func sizeInt64(i int64) (size int) { for ; i != 0 || size == 0; i >>= 8 { size++ } return } func writeInt64(bytes *Bytes, i int64) (size int) { for ; i != 0 || size == 0; i >>= 8 { // Write at least one byte even if the value is 0 bytes.writeBytes([]byte{byte(i)}) size++ } return } // parseInt treats the given bytes as a big-endian, signed integer and returns // the result. func parseInt32(bytes []byte) (int32, error) { ret64, err := parseInt64(bytes) if err != nil { return 0, err } if ret64 != int64(int32(ret64)) { return 0, StructuralError{"integer too large"} } return int32(ret64), nil } func sizeInt32(i int32) int { return sizeInt64(int64(i)) } func writeInt32(bytes *Bytes, i int32) int { return writeInt64(bytes, int64(i)) } var bigOne = big.NewInt(1) // // parseBigInt treats the given bytes as a big-endian, signed integer and returns // // the result. // func parseBigInt(bytes []byte) *big.Int { // ret := new(big.Int) // if len(bytes) > 0 && bytes[0]&0x80 == 0x80 { // // This is a negative number. // notBytes := make([]byte, len(bytes)) // for i := range notBytes { // notBytes[i] = ^bytes[i] // } // ret.SetBytes(notBytes) // ret.Add(ret, bigOne) // ret.Neg(ret) // return ret // } // ret.SetBytes(bytes) // return ret // } // // BIT STRING // // BitString is the structure to use when you want an ASN.1 BIT STRING type. A // // bit string is padded up to the nearest byte in memory and the number of // // valid bits is recorded. Padding bits will be zero. // type BitString struct { // Bytes []byte // bits packed into bytes. // BitLength int // length in bits. // } // // At returns the bit at the given index. If the index is out of range it // // returns false. // func (b BitString) At(i int) int { // if i < 0 || i >= b.BitLength { // return 0 // } // x := i / 8 // y := 7 - uint(i%8) // return int(b.Bytes[x]>>y) & 1 // } // // RightAlign returns a slice where the padding bits are at the beginning. The // // slice may share memory with the BitString. // func (b BitString) RightAlign() []byte { // shift := uint(8 - (b.BitLength % 8)) // if shift == 8 || len(b.Bytes) == 0 { // return b.Bytes // } // a := make([]byte, len(b.Bytes)) // a[0] = b.Bytes[0] >> shift // for i := 1; i < len(b.Bytes); i++ { // a[i] = b.Bytes[i-1] << (8 - shift) // a[i] |= b.Bytes[i] >> shift // } // return a // } // // parseBitString parses an ASN.1 bit string from the given byte slice and returns it. // func parseBitString(bytes []byte) (ret BitString, err error) { // if len(bytes) == 0 { // err = SyntaxError{"zero length BIT STRING"} // return // } // paddingBits := int(bytes[0]) // if paddingBits > 7 || // len(bytes) == 1 && paddingBits > 0 || // bytes[len(bytes)-1]&((1< 0 { // s += "." // } // s += strconv.Itoa(v) // } // return s // } // // parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and // // returns it. An object identifier is a sequence of variable length integers // // that are assigned in a hierarchy. // func parseObjectIdentifier(bytes []byte) (s []int, err error) { // if len(bytes) == 0 { // err = SyntaxError{"zero length OBJECT IDENTIFIER"} // return // } // // In the worst case, we get two elements from the first byte (which is // // encoded differently) and then every varint is a single byte long. // s = make([]int, len(bytes)+1) // // The first varint is 40*value1 + value2: // // According to this packing, value1 can take the values 0, 1 and 2 only. // // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, // // then there are no restrictions on value2. // v, offset, err := parseBase128Int(bytes, 0) // if err != nil { // return // } // if v < 80 { // s[0] = v / 40 // s[1] = v % 40 // } else { // s[0] = 2 // s[1] = v - 80 // } // i := 2 // for ; offset < len(bytes); i++ { // v, offset, err = parseBase128Int(bytes, offset) // if err != nil { // return // } // s[i] = v // } // s = s[0:i] // return // } // ENUMERATED // An Enumerated is represented as a plain int. type Enumerated int // FLAG // A Flag accepts any data and is set to true if present. type Flag bool // parseBase128Int parses a base-128 encoded int from the given offset in the // given byte slice. It returns the value and the new offset. func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) { offset = initOffset for shifted := 0; offset < len(bytes); shifted++ { if shifted > 4 { err = StructuralError{"base 128 integer too large"} return } ret <<= 7 b := bytes[offset] ret |= int(b & 0x7f) offset++ if b&0x80 == 0 { return } } err = SyntaxError{"truncated base 128 integer"} return } func sizeBase128Int(value int) (size int) { for i := value; i > 0; i >>= 7 { size++ } return } // Write start as the end of the slice and goes back // We assume we have enough size func writeBase128Int(bytes *Bytes, value int) (size int) { for ; value > 0 || size == 0; value >>= 7 { // Write at least one byte even if the value is 0 // Get the 7 lowest bits b := byte(value) & 0x7f if value < 128 { b |= 0x80 } bytes.writeBytes([]byte{b}) size++ } return } // // UTCTime // func parseUTCTime(bytes []byte) (ret time.Time, err error) { // s := string(bytes) // ret, err = time.Parse("0601021504Z0700", s) // if err != nil { // ret, err = time.Parse("060102150405Z0700", s) // } // if err == nil && ret.Year() >= 2050 { // // UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 // ret = ret.AddDate(-100, 0, 0) // } // return // } // // parseGeneralizedTime parses the GeneralizedTime from the given byte slice // // and returns the resulting time. // func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) { // return time.Parse("20060102150405Z0700", string(bytes)) // } // // PrintableString // // parsePrintableString parses a ASN.1 PrintableString from the given byte // // array and returns it. // func parsePrintableString(bytes []byte) (ret string, err error) { // for _, b := range bytes { // if !isPrintable(b) { // err = SyntaxError{"PrintableString contains invalid character"} // return // } // } // ret = string(bytes) // return // } // // isPrintable returns true iff the given b is in the ASN.1 PrintableString set. // func isPrintable(b byte) bool { // return 'a' <= b && b <= 'z' || // 'A' <= b && b <= 'Z' || // '0' <= b && b <= '9' || // '\'' <= b && b <= ')' || // '+' <= b && b <= '/' || // b == ' ' || // b == ':' || // b == '=' || // b == '?' || // // This is technically not allowed in a PrintableString. // // However, x509 certificates with wildcard strings don't // // always use the correct string type so we permit it. // b == '*' // } // // IA5String // // parseIA5String parses a ASN.1 IA5String (ASCII string) from the given // // byte slice and returns it. // func parseIA5String(bytes []byte) (ret string, err error) { // for _, b := range bytes { // if b >= 0x80 { // err = SyntaxError{"IA5String contains invalid character"} // return // } // } // ret = string(bytes) // return // } // // T61String // // parseT61String parses a ASN.1 T61String (8-bit clean string) from the given // // byte slice and returns it. // func parseT61String(bytes []byte) (ret string, err error) { // return string(bytes), nil // } // UTF8String // parseUTF8String parses a ASN.1 UTF8String (raw UTF-8) from the given byte // array and returns it. // func parseUTF8String(bytes []byte) (ret string, err error) { // return string(bytes), nil // } // func sizeUTF8String(s string) int { // return len(s) // } // func writeUTF8String(bytes *Bytes, s string) int { // return bytes.writeString(s) // } // Octet string func parseOctetString(bytes []byte) (ret []byte, err error) { return bytes, nil } func sizeOctetString(s []byte) int { return len(s) } func writeOctetString(bytes *Bytes, s []byte) int { return bytes.writeBytes(s) } // A RawValue represents an undecoded ASN.1 object. type RawValue struct { Class, Tag int IsCompound bool Bytes []byte FullBytes []byte // includes the tag and length } // RawContent is used to signal that the undecoded, DER data needs to be // preserved for a struct. To use it, the first field of the struct must have // this type. It's an error for any of the other fields to have this type. type RawContent []byte // Tagging // parseTagAndLength parses an ASN.1 tag and length pair from the given offset // into a byte slice. It returns the parsed data and the new offset. SET and // SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we // don't distinguish between ordered and unordered objects in this code. func parseTagAndLength(bytes []byte, initOffset int) (ret TagAndLength, offset int, err error) { offset = initOffset b := bytes[offset] offset++ ret.Class = int(b >> 6) ret.IsCompound = b&0x20 == 0x20 ret.Tag = int(b & 0x1f) // If the bottom five bits are set, then the tag number is actually base 128 // encoded afterwards if ret.Tag == 0x1f { ret.Tag, offset, err = parseBase128Int(bytes, offset) if err != nil { return } } if offset >= len(bytes) { err = SyntaxError{"truncated tag or length"} return } b = bytes[offset] offset++ if b&0x80 == 0 { // The length is encoded in the bottom 7 bits. ret.Length = int(b & 0x7f) } else { // Bottom 7 bits give the number of length bytes to follow. numBytes := int(b & 0x7f) if numBytes == 0 { err = SyntaxError{"indefinite length found (not DER)"} return } ret.Length = 0 for i := 0; i < numBytes; i++ { if offset >= len(bytes) { err = SyntaxError{"truncated tag or length"} return } b = bytes[offset] offset++ if ret.Length >= 1<<23 { // We can't shift ret.length up without // overflowing. err = StructuralError{"length too large"} return } ret.Length <<= 8 ret.Length |= int(b) if ret.Length == 0 { // DER requires that lengths be minimal. err = StructuralError{"superfluous leading zeros in length"} return } } } return } // func writeTagAndLength(out *forkableWriter, t tagAndLength) (err error) { // b := uint8(t.class) << 6 // if t.isCompound { // b |= 0x20 // } // if t.tag >= 31 { // b |= 0x1f // err = out.WriteByte(b) // if err != nil { // return // } // err = marshalBase128Int(out, int64(t.tag)) // if err != nil { // return // } // } else { // b |= uint8(t.tag) // err = out.WriteByte(b) // if err != nil { // return // } // } // if t.length >= 128 { // l := lengthLength(t.length) // err = out.WriteByte(0x80 | byte(l)) // if err != nil { // return // } // err = marshalLength(out, t.length) // if err != nil { // return // } // } else { // err = out.WriteByte(byte(t.length)) // if err != nil { // return // } // } // return nil // } func sizeTagAndLength(tag int, length int) (size int) { // Compute the size of the tag size = 1 if tag >= 31 { // Long-form identifier if the tag is greater than 30 // http://en.wikipedia.org/wiki/X.690#Identifier_tags_greater_than_30 size += sizeBase128Int(tag) } // Compute the size of the length using the definite form // http://en.wikipedia.org/wiki/X.690#The_definite_form size += 1 if length >= 128 { size += 1 for length > 255 { size++ length >>= 8 } } return } func writeTagAndLength(bytes *Bytes, t TagAndLength) (size int) { // We are writing backward, so write the length bytes first if t.Length < 0 { panic("Can't have a negative length") } else if t.Length >= 128 { lengthBytes := writeInt64(bytes, int64(t.Length)) bytes.writeBytes([]byte{byte(0x80 | byte(lengthBytes))}) size += lengthBytes + 1 } else if t.Length < 128 { size += bytes.writeBytes([]byte{byte(t.Length)}) } // Then write the tag b := uint8(t.Class) << 6 if t.IsCompound { b |= 0x20 } if t.Tag >= 31 { b |= 0x1f size += writeBase128Int(bytes, t.Tag) } else { b |= uint8(t.Tag) } size += bytes.writeBytes([]byte{byte(b)}) return } // // END encoding/asn1/asn1.go //