aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Shoemaker <roland@golang.org>2021-09-03 09:56:23 -0700
committerRoland Shoemaker <roland@golang.org>2022-02-09 21:57:04 +0000
commitcd6e0d7cad147b686f9f8066b651b0079e6f51c6 (patch)
tree130542dd8609c024e45574d1e505ba5f05b5f405
parent6a70ee2873b2367e2a0d6e7d7e167c072b99daf0 (diff)
downloadgo-cd6e0d7cad147b686f9f8066b651b0079e6f51c6.tar.gz
go-cd6e0d7cad147b686f9f8066b651b0079e6f51c6.zip
[release-branch.go1.17] crypto/x509: support NumericString in DN components
Updates #48171 Fixes #51000 Change-Id: Ia2e1920c0938a1f8659935a4f725a7e5090ef2c0 Reviewed-on: https://go-review.googlesource.com/c/go/+/347034 Trust: Roland Shoemaker <roland@golang.org> Run-TryBot: Roland Shoemaker <roland@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Filippo Valsorda <filippo@golang.org> (cherry picked from commit 896df422a7cecbace10f5877beeeb1476b6061ae) Reviewed-on: https://go-review.googlesource.com/c/go/+/382857 Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
-rw-r--r--src/crypto/x509/parser.go13
-rw-r--r--src/crypto/x509/parser_test.go102
2 files changed, 112 insertions, 3 deletions
diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go
index f085162a4e..9a500a8098 100644
--- a/src/crypto/x509/parser.go
+++ b/src/crypto/x509/parser.go
@@ -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:
@@ -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)
}
diff --git a/src/crypto/x509/parser_test.go b/src/crypto/x509/parser_test.go
new file mode 100644
index 0000000000..d7cf7ea758
--- /dev/null
+++ b/src/crypto/x509/parser_test.go
@@ -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)
+ }
+ })
+ }
+}