diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 4c9182d902..86d9e82aca 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -984,7 +984,7 @@ type distributionPoint struct { } type distributionPointName struct { - FullName asn1.RawValue `asn1:"optional,tag:0"` + FullName []asn1.RawValue `asn1:"optional,tag:0"` RelativeName pkix.RDNSequence `asn1:"optional,tag:1"` } @@ -1466,20 +1466,14 @@ func parseCertificate(in *certificate) (*Certificate, error) { for _, dp := range cdp { // Per RFC 5280, 4.2.1.13, one of distributionPoint or cRLIssuer may be empty. - if len(dp.DistributionPoint.FullName.Bytes) == 0 { + if len(dp.DistributionPoint.FullName) == 0 { continue } - var n asn1.RawValue - if _, err := asn1.Unmarshal(dp.DistributionPoint.FullName.Bytes, &n); err != nil { - return nil, err - } - // Trailing data after the fullName is - // allowed because other elements of - // the SEQUENCE can appear. - - if n.Tag == 6 { - out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(n.Bytes)) + for _, fullName := range dp.DistributionPoint.FullName { + if fullName.Tag == 6 { + out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(fullName.Bytes)) + } } } @@ -1946,11 +1940,11 @@ func buildExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId var crlDp []distributionPoint for _, name := range template.CRLDistributionPoints { - rawFullName, _ := asn1.Marshal(asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)}) - dp := distributionPoint{ DistributionPoint: distributionPointName{ - FullName: asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: rawFullName}, + FullName: []asn1.RawValue{ + asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)}, + }, }, } crlDp = append(crlDp, dp) diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 502f5d21d3..7d75727a8c 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -1891,3 +1891,58 @@ func TestEmptySubject(t *testing.T) { t.Fatal("SAN extension is missing") } + +// multipleURLsInCRLDPPEM contains two URLs in a single CRL DistributionPoint +// structure. It is taken from https://crt.sh/?id=12721534. +const multipleURLsInCRLDPPEM = ` +-----BEGIN CERTIFICATE----- +MIIF4TCCBMmgAwIBAgIQc+6uFePfrahUGpXs8lhiTzANBgkqhkiG9w0BAQsFADCB +8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy +dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1 +YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3 +dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh +IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD +LUFDQzAeFw0xNDA5MTgwODIxMDBaFw0zMDA5MTgwODIxMDBaMIGGMQswCQYDVQQG +EwJFUzEzMDEGA1UECgwqQ09OU09SQ0kgQURNSU5JU1RSQUNJTyBPQkVSVEEgREUg +Q0FUQUxVTllBMSowKAYDVQQLDCFTZXJ2ZWlzIFDDumJsaWNzIGRlIENlcnRpZmlj +YWNpw7MxFjAUBgNVBAMMDUVDLUNpdXRhZGFuaWEwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDFkHPRZPZlXTWZ5psJhbS/Gx+bxcTpGrlVQHHtIkgGz77y +TA7UZUFb2EQMncfbOhR0OkvQQn1aMvhObFJSR6nI+caf2D+h/m/InMl1MyH3S0Ak +YGZZsthnyC6KxqK2A/NApncrOreh70ULkQs45aOKsi1kR1W0zE+iFN+/P19P7AkL +Rl3bXBCVd8w+DLhcwRrkf1FCDw6cEqaFm3cGgf5cbBDMaVYAweWTxwBZAq2RbQAW +jE7mledcYghcZa4U6bUmCBPuLOnO8KMFAvH+aRzaf3ws5/ZoOVmryyLLJVZ54peZ +OwnP9EL4OuWzmXCjBifXR2IAblxs5JYj57tls45nAgMBAAGjggHaMIIB1jASBgNV +HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUC2hZPofI +oxUa4ECCIl+fHbLFNxUwHwYDVR0jBBgwFoAUoMOLRKo3pUW/l4Ba0fF4opvpXY0w +gdYGA1UdIASBzjCByzCByAYEVR0gADCBvzAxBggrBgEFBQcCARYlaHR0cHM6Ly93 +d3cuYW9jLmNhdC9DQVRDZXJ0L1JlZ3VsYWNpbzCBiQYIKwYBBQUHAgIwfQx7QXF1 +ZXN0IGNlcnRpZmljYXQgw6lzIGVtw6hzIMO6bmljYSBpIGV4Y2x1c2l2YW1lbnQg +YSBFbnRpdGF0cyBkZSBDZXJ0aWZpY2FjacOzLiBWZWdldSBodHRwczovL3d3dy5h +b2MuY2F0L0NBVENlcnQvUmVndWxhY2lvMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEF +BQcwAYYXaHR0cDovL29jc3AuY2F0Y2VydC5jYXQwYgYDVR0fBFswWTBXoFWgU4Yn +aHR0cDovL2Vwc2NkLmNhdGNlcnQubmV0L2NybC9lYy1hY2MuY3JshihodHRwOi8v +ZXBzY2QyLmNhdGNlcnQubmV0L2NybC9lYy1hY2MuY3JsMA0GCSqGSIb3DQEBCwUA +A4IBAQChqFTjlAH5PyIhLjLgEs68CyNNC1+vDuZXRhy22TI83JcvGmQrZosPvVIL +PsUXx+C06Pfqmh48Q9S89X9K8w1SdJxP/rZeGEoRiKpwvQzM4ArD9QxyC8jirxex +3Umg9Ai/sXQ+1lBf6xw4HfUUr1WIp7pNHj0ZWLo106urqktcdeAFWme+/klis5fu +labCSVPuT/QpwakPrtqOhRms8vgpKiXa/eLtL9ZiA28X/Mker0zlAeTA7Z7uAnp6 +oPJTlZu1Gg1ZDJueTWWsLlO+P+Wzm3MRRIbcgdRzm4mdO7ubu26SzX/aQXDhuih+ +eVxXDTCfs7GUlxnjOp5j559X/N0A +-----END CERTIFICATE----- +` + +func TestMultipleURLsInCRLDP(t *testing.T) { + block, _ := pem.Decode([]byte(multipleURLsInCRLDPPEM)) + cert, err := ParseCertificate(block.Bytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } + + want := []string{ + "http://epscd.catcert.net/crl/ec-acc.crl", + "http://epscd2.catcert.net/crl/ec-acc.crl", + } + if got := cert.CRLDistributionPoints; !reflect.DeepEqual(got, want) { + t.Errorf("CRL distribution points = %#v, want #%v", got, want) + } +}