aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/encoding/asn1/asn1.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/encoding/asn1/asn1.go')
-rw-r--r--libgo/go/encoding/asn1/asn1.go111
1 files changed, 72 insertions, 39 deletions
diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go
index 2ac411a..8bafefd 100644
--- a/libgo/go/encoding/asn1/asn1.go
+++ b/libgo/go/encoding/asn1/asn1.go
@@ -71,9 +71,28 @@ func parseBool(bytes []byte) (ret bool, err error) {
// INTEGER
+// checkInteger returns nil if the given bytes are a valid DER-encoded
+// INTEGER and an error otherwise.
+func checkInteger(bytes []byte) error {
+ if len(bytes) == 0 {
+ return StructuralError{"empty integer"}
+ }
+ if len(bytes) == 1 {
+ return nil
+ }
+ if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) {
+ return StructuralError{"integer not minimally-encoded"}
+ }
+ return nil
+}
+
// parseInt64 treats the given bytes as a big-endian, signed integer and
// returns the result.
func parseInt64(bytes []byte) (ret int64, err error) {
+ err = checkInteger(bytes)
+ if err != nil {
+ return
+ }
if len(bytes) > 8 {
// We'll overflow an int64 in this case.
err = StructuralError{"integer too large"}
@@ -93,6 +112,9 @@ func parseInt64(bytes []byte) (ret int64, err error) {
// parseInt treats the given bytes as a big-endian, signed integer and returns
// the result.
func parseInt32(bytes []byte) (int32, error) {
+ if err := checkInteger(bytes); err != nil {
+ return 0, err
+ }
ret64, err := parseInt64(bytes)
if err != nil {
return 0, err
@@ -107,7 +129,10 @@ 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 {
+func parseBigInt(bytes []byte) (*big.Int, error) {
+ if err := checkInteger(bytes); err != nil {
+ return nil, err
+ }
ret := new(big.Int)
if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
// This is a negative number.
@@ -118,10 +143,10 @@ func parseBigInt(bytes []byte) *big.Int {
ret.SetBytes(notBytes)
ret.Add(ret, bigOne)
ret.Neg(ret)
- return ret
+ return ret, nil
}
ret.SetBytes(bytes)
- return ret
+ return ret, nil
}
// BIT STRING
@@ -269,7 +294,7 @@ type Flag bool
func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
offset = initOffset
for shifted := 0; offset < len(bytes); shifted++ {
- if shifted > 4 {
+ if shifted == 4 {
err = StructuralError{"base 128 integer too large"}
return
}
@@ -475,6 +500,11 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
return
}
}
+ // Short lengths must be encoded in short form.
+ if ret.length < 0x80 {
+ err = StructuralError{"non-minimal length"}
+ return
+ }
}
return
@@ -500,17 +530,17 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type
return
}
switch t.tag {
- case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
+ case TagIA5String, TagGeneralString, TagT61String, TagUTF8String:
// We pretend that various other string types are
// PRINTABLE STRINGs so that a sequence of them can be
// parsed into a []string.
- t.tag = tagPrintableString
- case tagGeneralizedTime, tagUTCTime:
+ t.tag = TagPrintableString
+ case TagGeneralizedTime, TagUTCTime:
// Likewise, both time types are treated the same.
- t.tag = tagUTCTime
+ t.tag = TagUTCTime
}
- if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag {
+ if t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag {
err = StructuralError{"sequence tag mismatch"}
return
}
@@ -594,28 +624,28 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
return
}
var result interface{}
- if !t.isCompound && t.class == classUniversal {
+ if !t.isCompound && t.class == ClassUniversal {
innerBytes := bytes[offset : offset+t.length]
switch t.tag {
- case tagPrintableString:
+ case TagPrintableString:
result, err = parsePrintableString(innerBytes)
- case tagIA5String:
+ case TagIA5String:
result, err = parseIA5String(innerBytes)
- case tagT61String:
+ case TagT61String:
result, err = parseT61String(innerBytes)
- case tagUTF8String:
+ case TagUTF8String:
result, err = parseUTF8String(innerBytes)
- case tagInteger:
+ case TagInteger:
result, err = parseInt64(innerBytes)
- case tagBitString:
+ case TagBitString:
result, err = parseBitString(innerBytes)
- case tagOID:
+ case TagOID:
result, err = parseObjectIdentifier(innerBytes)
- case tagUTCTime:
+ case TagUTCTime:
result, err = parseUTCTime(innerBytes)
- case tagGeneralizedTime:
+ case TagGeneralizedTime:
result, err = parseGeneralizedTime(innerBytes)
- case tagOctetString:
+ case TagOctetString:
result = innerBytes
default:
// If we don't know how to handle the type, we just leave Value as nil.
@@ -641,9 +671,9 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
return
}
if params.explicit {
- expectedClass := classContextSpecific
+ expectedClass := ClassContextSpecific
if params.application {
- expectedClass = classApplication
+ expectedClass = ClassApplication
}
if offset == len(bytes) {
err = StructuralError{"explicit tag has no child"}
@@ -679,10 +709,10 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
// type string. getUniversalType returns the tag for PrintableString
// when it sees a string, so if we see a different string type on the
// wire, we change the universal type to match.
- if universalTag == tagPrintableString {
- if t.class == classUniversal {
+ if universalTag == TagPrintableString {
+ if t.class == ClassUniversal {
switch t.tag {
- case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
+ case TagIA5String, TagGeneralString, TagT61String, TagUTF8String:
universalTag = t.tag
}
} else if params.stringType != 0 {
@@ -692,24 +722,24 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
// Special case for time: UTCTime and GeneralizedTime both map to the
// Go type time.Time.
- if universalTag == tagUTCTime && t.tag == tagGeneralizedTime && t.class == classUniversal {
- universalTag = tagGeneralizedTime
+ if universalTag == TagUTCTime && t.tag == TagGeneralizedTime && t.class == ClassUniversal {
+ universalTag = TagGeneralizedTime
}
if params.set {
- universalTag = tagSet
+ universalTag = TagSet
}
- expectedClass := classUniversal
+ expectedClass := ClassUniversal
expectedTag := universalTag
if !params.explicit && params.tag != nil {
- expectedClass = classContextSpecific
+ expectedClass = ClassContextSpecific
expectedTag = *params.tag
}
if !params.explicit && params.application && params.tag != nil {
- expectedClass = classApplication
+ expectedClass = ClassApplication
expectedTag = *params.tag
}
@@ -751,7 +781,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
case timeType:
var time time.Time
var err1 error
- if universalTag == tagUTCTime {
+ if universalTag == TagUTCTime {
time, err1 = parseUTCTime(innerBytes)
} else {
time, err1 = parseGeneralizedTime(innerBytes)
@@ -772,8 +802,11 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
v.SetBool(true)
return
case bigIntType:
- parsedInt := parseBigInt(innerBytes)
- v.Set(reflect.ValueOf(parsedInt))
+ parsedInt, err1 := parseBigInt(innerBytes)
+ if err1 == nil {
+ v.Set(reflect.ValueOf(parsedInt))
+ }
+ err = err1
return
}
switch val := v; val.Kind() {
@@ -840,15 +873,15 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
case reflect.String:
var v string
switch universalTag {
- case tagPrintableString:
+ case TagPrintableString:
v, err = parsePrintableString(innerBytes)
- case tagIA5String:
+ case TagIA5String:
v, err = parseIA5String(innerBytes)
- case tagT61String:
+ case TagT61String:
v, err = parseT61String(innerBytes)
- case tagUTF8String:
+ case TagUTF8String:
v, err = parseUTF8String(innerBytes)
- case tagGeneralString:
+ case TagGeneralString:
// GeneralString is specified in ISO-2022/ECMA-35,
// A brief review suggests that it includes structures
// that allow the encoding to change midstring and