diff --git a/src/pkg/crypto/x509/x509.go b/src/pkg/crypto/x509/x509.go index d789e5c560..7dea7b66ec 100644 --- a/src/pkg/crypto/x509/x509.go +++ b/src/pkg/crypto/x509/x509.go @@ -472,6 +472,9 @@ type Certificate struct { PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical. PermittedDNSDomains []string + // CRL Distribution Points + CRLDistributionPoints []string + PolicyIdentifiers []asn1.ObjectIdentifier } @@ -659,6 +662,18 @@ type generalSubtree struct { Name string `asn1:"tag:2,optional,ia5"` } +// RFC 5280, 4.2.1.14 +type distributionPoint struct { + DistributionPoint distributionPointName `asn1:"optional,tag:0"` + Reason asn1.BitString `asn1:"optional,tag:1"` + CRLIssuer asn1.RawValue `asn1:"optional,tag:2"` +} + +type distributionPointName struct { + FullName asn1.RawValue `asn1:"optional,tag:0"` + RelativeName pkix.RDNSequence `asn1:"optional,tag:1"` +} + func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) { asn1Data := keyData.PublicKey.RightAlign() switch algo { @@ -896,6 +911,39 @@ func parseCertificate(in *certificate) (*Certificate, error) { } continue + case 31: + // RFC 5280, 4.2.1.14 + + // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + // + // DistributionPoint ::= SEQUENCE { + // distributionPoint [0] DistributionPointName OPTIONAL, + // reasons [1] ReasonFlags OPTIONAL, + // cRLIssuer [2] GeneralNames OPTIONAL } + // + // DistributionPointName ::= CHOICE { + // fullName [0] GeneralNames, + // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + + var cdp []distributionPoint + _, err := asn1.Unmarshal(e.Value, &cdp) + if err != nil { + return nil, err + } + + for _, dp := range cdp { + var n asn1.RawValue + _, err = asn1.Unmarshal(dp.DistributionPoint.FullName.Bytes, &n) + if err != nil { + return nil, err + } + + if n.Tag == 6 { + out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(n.Bytes)) + } + } + continue + case 35: // RFC 5280, 4.2.1.1 var a authKeyId @@ -1011,18 +1059,19 @@ func reverseBitsInAByte(in byte) byte { } var ( - oidExtensionSubjectKeyId = []int{2, 5, 29, 14} - oidExtensionKeyUsage = []int{2, 5, 29, 15} - oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37} - oidExtensionAuthorityKeyId = []int{2, 5, 29, 35} - oidExtensionBasicConstraints = []int{2, 5, 29, 19} - oidExtensionSubjectAltName = []int{2, 5, 29, 17} - oidExtensionCertificatePolicies = []int{2, 5, 29, 32} - oidExtensionNameConstraints = []int{2, 5, 29, 30} + oidExtensionSubjectKeyId = []int{2, 5, 29, 14} + oidExtensionKeyUsage = []int{2, 5, 29, 15} + oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37} + oidExtensionAuthorityKeyId = []int{2, 5, 29, 35} + oidExtensionBasicConstraints = []int{2, 5, 29, 19} + oidExtensionSubjectAltName = []int{2, 5, 29, 17} + oidExtensionCertificatePolicies = []int{2, 5, 29, 32} + oidExtensionNameConstraints = []int{2, 5, 29, 30} + oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31} ) func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { - ret = make([]pkix.Extension, 8 /* maximum number of elements. */) + ret = make([]pkix.Extension, 9 /* maximum number of elements. */) n := 0 if template.KeyUsage != 0 { @@ -1147,6 +1196,28 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { n++ } + if len(template.CRLDistributionPoints) > 0 { + ret[n].Id = oidExtensionCRLDistributionPoints + + 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, Bytes: rawFullName}, + }, + } + crlDp = append(crlDp, dp) + } + + ret[n].Value, err = asn1.Marshal(crlDp) + if err != nil { + return + } + n++ + } + // Adding another extension here? Remember to update the maximum number // of elements in the make() at the top of the function. diff --git a/src/pkg/crypto/x509/x509_test.go b/src/pkg/crypto/x509/x509_test.go index 123b1cfc84..08dd09f926 100644 --- a/src/pkg/crypto/x509/x509_test.go +++ b/src/pkg/crypto/x509/x509_test.go @@ -336,6 +336,8 @@ func TestCreateSelfSignedCertificate(t *testing.T) { PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}}, PermittedDNSDomains: []string{".example.com", "example.com"}, + + CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"}, } derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv) @@ -386,6 +388,10 @@ func TestCreateSelfSignedCertificate(t *testing.T) { t.Errorf("%s: SAN IPs differ from template. Got %v, want %v", test.name, cert.IPAddresses, template.IPAddresses) } + if !reflect.DeepEqual(cert.CRLDistributionPoints, template.CRLDistributionPoints) { + t.Errorf("%s: CRL distribution points differ from template. Got %v, want %v", test.name, cert.CRLDistributionPoints, template.CRLDistributionPoints) + } + if test.checkSig { err = cert.CheckSignatureFrom(cert) if err != nil {