Skip to content

Commit

Permalink
[release-branch.go1.17] crypto/x509: support NumericString in DN comp…
Browse files Browse the repository at this point in the history
…onents

Updates #48171
Fixes #51000

Change-Id: Ia2e1920c0938a1f8659935a4f725a7e5090ef2c0
Reviewed-on: https://go-review.googlesource.com/c/go/+/347034
Trust: Roland Shoemaker <[email protected]>
Run-TryBot: Roland Shoemaker <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Filippo Valsorda <[email protected]>
(cherry picked from commit 896df42)
Reviewed-on: https://go-review.googlesource.com/c/go/+/382857
Reviewed-by: Emmanuel Odeke <[email protected]>
  • Loading branch information
rolandshoemaker committed Feb 9, 2022
1 parent 6a70ee2 commit cd6e0d7
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 3 deletions.
13 changes: 10 additions & 3 deletions src/crypto/x509/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ func isPrintable(b byte) bool {
}

// parseASN1String parses the ASN.1 string types T61String, PrintableString,
// UTF8String, BMPString, and IA5String. This is mostly copied from the
// respective encoding/asn1.parse... methods, rather than just increasing
// the API surface of that package.
// UTF8String, BMPString, IA5String, and NumericString. This is mostly copied
// from the respective encoding/asn1.parse... methods, rather than just
// increasing the API surface of that package.
func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) {
switch tag {
case cryptobyte_asn1.T61String:
Expand Down Expand Up @@ -93,6 +93,13 @@ func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) {
return "", errors.New("invalid IA5String")
}
return s, nil
case cryptobyte_asn1.Tag(asn1.TagNumericString):
for _, b := range value {
if !('0' <= b && b <= '9' || b == ' ') {
return "", errors.New("invalid NumericString")
}
}
return string(value), nil
}
return "", fmt.Errorf("unsupported string type: %v", tag)
}
Expand Down
102 changes: 102 additions & 0 deletions src/crypto/x509/parser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright 2021 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 x509

import (
"encoding/asn1"
"testing"

cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
)

func TestParseASN1String(t *testing.T) {
tests := []struct {
name string
tag cryptobyte_asn1.Tag
value []byte
expected string
expectedErr string
}{
{
name: "T61String",
tag: cryptobyte_asn1.T61String,
value: []byte{80, 81, 82},
expected: string("PQR"),
},
{
name: "PrintableString",
tag: cryptobyte_asn1.PrintableString,
value: []byte{80, 81, 82},
expected: string("PQR"),
},
{
name: "PrintableString (invalid)",
tag: cryptobyte_asn1.PrintableString,
value: []byte{1, 2, 3},
expectedErr: "invalid PrintableString",
},
{
name: "UTF8String",
tag: cryptobyte_asn1.UTF8String,
value: []byte{80, 81, 82},
expected: string("PQR"),
},
{
name: "UTF8String (invalid)",
tag: cryptobyte_asn1.UTF8String,
value: []byte{255},
expectedErr: "invalid UTF-8 string",
},
{
name: "BMPString",
tag: cryptobyte_asn1.Tag(asn1.TagBMPString),
value: []byte{80, 81},
expected: string("偑"),
},
{
name: "BMPString (invalid length)",
tag: cryptobyte_asn1.Tag(asn1.TagBMPString),
value: []byte{255},
expectedErr: "invalid BMPString",
},
{
name: "IA5String",
tag: cryptobyte_asn1.IA5String,
value: []byte{80, 81},
expected: string("PQ"),
},
{
name: "IA5String (invalid)",
tag: cryptobyte_asn1.IA5String,
value: []byte{255},
expectedErr: "invalid IA5String",
},
{
name: "NumericString",
tag: cryptobyte_asn1.Tag(asn1.TagNumericString),
value: []byte{49, 50},
expected: string("12"),
},
{
name: "NumericString (invalid)",
tag: cryptobyte_asn1.Tag(asn1.TagNumericString),
value: []byte{80},
expectedErr: "invalid NumericString",
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
out, err := parseASN1String(tc.tag, tc.value)
if err != nil && err.Error() != tc.expectedErr {
t.Fatalf("parseASN1String returned unexpected error: got %q, want %q", err, tc.expectedErr)
} else if err == nil && tc.expectedErr != "" {
t.Fatalf("parseASN1String didn't fail, expected: %s", tc.expectedErr)
}
if out != tc.expected {
t.Fatalf("parseASN1String returned unexpected value: got %q, want %q", out, tc.expected)
}
})
}
}

0 comments on commit cd6e0d7

Please sign in to comment.