Skip to content

Commit 896df42

Browse files
crypto/x509: support NumericString in DN components
Fixes #48171 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]>
1 parent 1ab8273 commit 896df42

2 files changed

Lines changed: 112 additions & 3 deletions

File tree

src/crypto/x509/parser.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ func isPrintable(b byte) bool {
5151
}
5252

5353
// parseASN1String parses the ASN.1 string types T61String, PrintableString,
54-
// UTF8String, BMPString, and IA5String. This is mostly copied from the
55-
// respective encoding/asn1.parse... methods, rather than just increasing
56-
// the API surface of that package.
54+
// UTF8String, BMPString, IA5String, and NumericString. This is mostly copied
55+
// from the respective encoding/asn1.parse... methods, rather than just
56+
// increasing the API surface of that package.
5757
func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) {
5858
switch tag {
5959
case cryptobyte_asn1.T61String:
@@ -93,6 +93,13 @@ func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) {
9393
return "", errors.New("invalid IA5String")
9494
}
9595
return s, nil
96+
case cryptobyte_asn1.Tag(asn1.TagNumericString):
97+
for _, b := range value {
98+
if !('0' <= b && b <= '9' || b == ' ') {
99+
return "", errors.New("invalid NumericString")
100+
}
101+
}
102+
return string(value), nil
96103
}
97104
return "", fmt.Errorf("unsupported string type: %v", tag)
98105
}

src/crypto/x509/parser_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
package x509
5+
6+
import (
7+
"encoding/asn1"
8+
"testing"
9+
10+
cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
11+
)
12+
13+
func TestParseASN1String(t *testing.T) {
14+
tests := []struct {
15+
name string
16+
tag cryptobyte_asn1.Tag
17+
value []byte
18+
expected string
19+
expectedErr string
20+
}{
21+
{
22+
name: "T61String",
23+
tag: cryptobyte_asn1.T61String,
24+
value: []byte{80, 81, 82},
25+
expected: string("PQR"),
26+
},
27+
{
28+
name: "PrintableString",
29+
tag: cryptobyte_asn1.PrintableString,
30+
value: []byte{80, 81, 82},
31+
expected: string("PQR"),
32+
},
33+
{
34+
name: "PrintableString (invalid)",
35+
tag: cryptobyte_asn1.PrintableString,
36+
value: []byte{1, 2, 3},
37+
expectedErr: "invalid PrintableString",
38+
},
39+
{
40+
name: "UTF8String",
41+
tag: cryptobyte_asn1.UTF8String,
42+
value: []byte{80, 81, 82},
43+
expected: string("PQR"),
44+
},
45+
{
46+
name: "UTF8String (invalid)",
47+
tag: cryptobyte_asn1.UTF8String,
48+
value: []byte{255},
49+
expectedErr: "invalid UTF-8 string",
50+
},
51+
{
52+
name: "BMPString",
53+
tag: cryptobyte_asn1.Tag(asn1.TagBMPString),
54+
value: []byte{80, 81},
55+
expected: string("偑"),
56+
},
57+
{
58+
name: "BMPString (invalid length)",
59+
tag: cryptobyte_asn1.Tag(asn1.TagBMPString),
60+
value: []byte{255},
61+
expectedErr: "invalid BMPString",
62+
},
63+
{
64+
name: "IA5String",
65+
tag: cryptobyte_asn1.IA5String,
66+
value: []byte{80, 81},
67+
expected: string("PQ"),
68+
},
69+
{
70+
name: "IA5String (invalid)",
71+
tag: cryptobyte_asn1.IA5String,
72+
value: []byte{255},
73+
expectedErr: "invalid IA5String",
74+
},
75+
{
76+
name: "NumericString",
77+
tag: cryptobyte_asn1.Tag(asn1.TagNumericString),
78+
value: []byte{49, 50},
79+
expected: string("12"),
80+
},
81+
{
82+
name: "NumericString (invalid)",
83+
tag: cryptobyte_asn1.Tag(asn1.TagNumericString),
84+
value: []byte{80},
85+
expectedErr: "invalid NumericString",
86+
},
87+
}
88+
89+
for _, tc := range tests {
90+
t.Run(tc.name, func(t *testing.T) {
91+
out, err := parseASN1String(tc.tag, tc.value)
92+
if err != nil && err.Error() != tc.expectedErr {
93+
t.Fatalf("parseASN1String returned unexpected error: got %q, want %q", err, tc.expectedErr)
94+
} else if err == nil && tc.expectedErr != "" {
95+
t.Fatalf("parseASN1String didn't fail, expected: %s", tc.expectedErr)
96+
}
97+
if out != tc.expected {
98+
t.Fatalf("parseASN1String returned unexpected value: got %q, want %q", out, tc.expected)
99+
}
100+
})
101+
}
102+
}

0 commit comments

Comments
 (0)