Skip to content

Commit d8a6c99

Browse files
committed
crypto/x509: Validate certificates with unsorted SET values in RDNs
1 parent a8e99ab commit d8a6c99

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

src/crypto/x509/parser.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,31 @@ func parseName(raw cryptobyte.String) (*pkix.RDNSequence, error) {
150150
for !raw.Empty() {
151151
var rdnSet pkix.RelativeDistinguishedNameSET
152152
var set cryptobyte.String
153-
if !raw.ReadASN1(&set, cryptobyte_asn1.SET) {
153+
var rawSet cryptobyte.String
154+
155+
if !raw.ReadASN1Element(&rawSet, cryptobyte_asn1.SET) {
156+
return nil, errors.New("x509: invalid RDNSequence")
157+
}
158+
159+
if !rawSet.ReadASN1(&set, cryptobyte_asn1.SET) {
154160
return nil, errors.New("x509: invalid RDNSequence")
155161
}
162+
163+
var rawAttrs []cryptobyte.String
164+
156165
for !set.Empty() {
157166
var atav cryptobyte.String
158-
if !set.ReadASN1(&atav, cryptobyte_asn1.SEQUENCE) {
167+
var rawAttr cryptobyte.String
168+
169+
if !set.ReadASN1Element(&rawAttr, cryptobyte_asn1.SEQUENCE) {
159170
return nil, errors.New("x509: invalid RDNSequence: invalid attribute")
160171
}
172+
rawAttrs = append(rawAttrs, rawAttr)
173+
174+
if !rawAttr.ReadASN1(&atav, cryptobyte_asn1.SEQUENCE) {
175+
return nil, errors.New("x509: invalid RDNSequence: invalid attribute")
176+
}
177+
161178
var attr pkix.AttributeTypeAndValue
162179
if !atav.ReadASN1ObjectIdentifier(&attr.Type) {
163180
return nil, errors.New("x509: invalid RDNSequence: invalid attribute type")
@@ -175,6 +192,18 @@ func parseName(raw cryptobyte.String) (*pkix.RDNSequence, error) {
175192
rdnSet = append(rdnSet, attr)
176193
}
177194

195+
// Verify that the SET values are sorted according to DER encoding rules
196+
// as required by X.690 section 11.6
197+
if len(rawAttrs) > 1 {
198+
for i := 1; i < len(rawAttrs); i++ {
199+
// Compare each attribute with the previous one
200+
// In DER, they must be in ascending order when compared as octet strings
201+
if bytes.Compare(rawAttrs[i-1], rawAttrs[i]) > 0 {
202+
return nil, errors.New("x509: invalid RDNSequence: SET values not in ascending order")
203+
}
204+
}
205+
}
206+
178207
rdnSeq = append(rdnSeq, rdnSet)
179208
}
180209

src/crypto/x509/parser_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package x509
66

77
import (
88
"encoding/asn1"
9+
"encoding/base64"
910
"encoding/pem"
1011
"os"
1112
"testing"
@@ -251,3 +252,20 @@ d5l1tRhScKu2NBgm74nYmJxJYgvuTA38wGhRrGU=
251252
}
252253
}
253254
}
255+
256+
func TestUnsortedSETInRDN(t *testing.T) {
257+
// This certificate has an unsorted SET in its RDN
258+
certB64 := "MIIFFDCCAvygAwIBAgIUb6hhfTZ9YpBB9FUvC1IUFrL3KAgwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkJKMQ0wCwYDVQQKDARKZWZlMRUwEwYDVQQDDAxKZWZlIFJvb3QgQ0ExEDAOBgNVBAcTB0JlaWppbmcwHhcNMjUwNTE2MjEwMjE2WhcNMjYwNTE2MjEwMjE2WjBSMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQkoxDTALBgNVBAoMBEplZmUxFTATBgNVBAMMDEplZmUgUm9vdCBDQTEQMA4GA1UEBxMHQmVpamluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAONdnqNcvwTNTKLCJMQzfBW8CjfMRxZI96NU+AYvvwTaSlEXxGY93KD1HsrqXRb4lUhxXVSdbdGGtCwF20zKSoJmcikMW21+9dW6hxkDJVp/E2BKgb1nBJj7d0FgVZyEcjgX2xbHcUdvBJg5IB13MPxcfRfGdHJ8vbA3NFJGdxJgqGb1XQHuU5ql3UGK0UMYHoLAA8ZeUZ7RgdCXAyM2XxF5lXDfzn5/DrlcFbMCLtA4JpbU87QnTIZxWQQ0LLz+FJ/M6sqkTL+CsOWRKXH6TPcyXLCrjuDa7pM/8vVkCX/oeyqwMvYEYV/q+JPHQ34UdhX1g7/OXZh+nGcgV4USOQECAwEAAaOCAQEwgf4wHQYDVR0OBBYEFA2Dg0Oa1UgW3qF3Q6cvq6fvp5wlMIHBBgNVHSMEgbkwgbaAFA2Dg0Oa1UgW3qF3Q6cvq6fvp5wloYGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEplZmUxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEXMBUGCSqGSIb3DQEJARYIQUBCLkMuRE2CFG+oYX02fWKQQfRVLwtSFBay9ygIMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAZkWrFDnDN7aJYxgaLbTxvPQiUEw56GZfYaEH/gHSfkUiWvW8/Ub6Gp0rb/UEwu/9pPvs6QnwqLwBHkBpZX6lF1f5ltBbNzPdFVgQN1GdvETofyqQOo3hRbZ3vfEP7Yro7qXWFmwJwM1lMgTWuPpwxeGOqKR0o8C0dEssPJePAJRQHQHyldQ5Ie96KgLqRjxqx/7A4EQyZ3j3kWGnEY+QiHEEH9SgJ/iVkFuQf479VdMVLgcP9eEF+eKczcHINIGLvYL/9XYxKmfKLIKcZTYpxHdXJRIGLQ27IbXdKeZG0l9+ztLNCkG5fqCDZosfYvN0CIIpkQDQxnPnV4MVOXUhZBVW5Q=="
259+
260+
der, err := base64.StdEncoding.DecodeString(certB64)
261+
if err != nil {
262+
t.Fatalf("Failed to decode certificate: %v", err)
263+
}
264+
265+
_, err = ParseCertificate(der)
266+
if err == nil {
267+
t.Errorf("Expected ParseCertificate to fail due to unsorted SET values in RDN, but it succeeded")
268+
} else if err.Error() != "x509: malformed certificate" {
269+
t.Errorf("Expected error 'x509: malformed certificate', got: %v", err)
270+
}
271+
}

0 commit comments

Comments
 (0)