Skip to content

Commit

Permalink
encoding/asn1: don't encode strings with '*' as PrintableString.
Browse files Browse the repository at this point in the history
The '*' character is not allowed in ASN.1 PrintableString. However, due
to wide-spread use, we permit it so that we can parse many certificates
with wildcards. However, that also meant that generic strings with
asterisks in would be encoded as PrintableString.

This change makes the default for such strings to be UTF8String. Thus,
while the code PrintableStrings containing '*', it will not generate
them unless the string type was specified in the struct field tag.

Change-Id: I2d458da36649427352eeaa50a1b6020108b2ccbd
Reviewed-on: https://go-review.googlesource.com/68990
Reviewed-by: Adam Langley <agl@golang.org>
  • Loading branch information
agl committed Oct 9, 2017
1 parent d402343 commit 3b186db
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 5 deletions.
15 changes: 12 additions & 3 deletions src/encoding/asn1/asn1.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) {
// array and returns it.
func parsePrintableString(bytes []byte) (ret string, err error) {
for _, b := range bytes {
if !isPrintable(b) {
if !isPrintable(b, allowAsterisk) {
err = SyntaxError{"PrintableString contains invalid character"}
return
}
Expand All @@ -387,8 +387,17 @@ func parsePrintableString(bytes []byte) (ret string, err error) {
return
}

type asteriskFlag bool

const (
allowAsterisk asteriskFlag = true
rejectAsterisk asteriskFlag = false
)

// isPrintable reports whether the given b is in the ASN.1 PrintableString set.
func isPrintable(b byte) bool {
// If asterisk is allowAsterisk then '*' is also allowed, reflecting existing
// practice.
func isPrintable(b byte, asterisk asteriskFlag) bool {
return 'a' <= b && b <= 'z' ||
'A' <= b && b <= 'Z' ||
'0' <= b && b <= '9' ||
Expand All @@ -401,7 +410,7 @@ func isPrintable(b byte) bool {
// 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 == '*'
(bool(asterisk) && b == '*')
}

// IA5String
Expand Down
7 changes: 5 additions & 2 deletions src/encoding/asn1/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,10 @@ func makeObjectIdentifier(oid []int) (e encoder, err error) {

func makePrintableString(s string) (e encoder, err error) {
for i := 0; i < len(s); i++ {
if !isPrintable(s[i]) {
// The asterisk is often used in PrintableString, even though
// it is invalid. If a PrintableString was specifically
// requested then the asterisk is permitted by this code.
if !isPrintable(s[i], allowAsterisk) {
return nil, StructuralError{"PrintableString contains invalid character"}
}
}
Expand Down Expand Up @@ -576,7 +579,7 @@ func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) {
// a PrintableString if the character set in the string is
// sufficiently limited, otherwise we'll use a UTF8String.
for _, r := range v.String() {
if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
if r >= utf8.RuneSelf || !isPrintable(byte(r), rejectAsterisk) {
if !utf8.ValidString(v.String()) {
return nil, errors.New("asn1: string not valid UTF-8")
}
Expand Down
6 changes: 6 additions & 0 deletions src/encoding/asn1/marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ type printableStringTest struct {
A string `asn1:"printable"`
}

type genericStringTest struct {
A string
}

type optionalRawValueTest struct {
A RawValue `asn1:"optional"`
}
Expand Down Expand Up @@ -147,6 +151,8 @@ var marshalTests = []marshalTest{
{optionalRawValueTest{}, "3000"},
{printableStringTest{"test"}, "3006130474657374"},
{printableStringTest{"test*"}, "30071305746573742a"},
{genericStringTest{"test"}, "3006130474657374"},
{genericStringTest{"test*"}, "30070c05746573742a"},
{rawContentsStruct{nil, 64}, "3003020140"},
{rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"},
{RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"},
Expand Down

0 comments on commit 3b186db

Please sign in to comment.