Commit 4bd79e74 authored by Paul van Brouwershaven's avatar Paul van Brouwershaven Committed by Brad Fitzpatrick

crypto/x509: Added RFC 5280, section 4.2.1.14 to parseCertificate and buildExtensions

Support for CRL Distribution Points

R=golang-dev, agl, bradfitz
CC=golang-dev
https://golang.org/cl/10258043
parent 944a2605
...@@ -472,6 +472,9 @@ type Certificate struct { ...@@ -472,6 +472,9 @@ type Certificate struct {
PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical. PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
PermittedDNSDomains []string PermittedDNSDomains []string
// CRL Distribution Points
CRLDistributionPoints []string
PolicyIdentifiers []asn1.ObjectIdentifier PolicyIdentifiers []asn1.ObjectIdentifier
} }
...@@ -659,6 +662,18 @@ type generalSubtree struct { ...@@ -659,6 +662,18 @@ type generalSubtree struct {
Name string `asn1:"tag:2,optional,ia5"` 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) { func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
asn1Data := keyData.PublicKey.RightAlign() asn1Data := keyData.PublicKey.RightAlign()
switch algo { switch algo {
...@@ -896,6 +911,39 @@ func parseCertificate(in *certificate) (*Certificate, error) { ...@@ -896,6 +911,39 @@ func parseCertificate(in *certificate) (*Certificate, error) {
} }
continue 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: case 35:
// RFC 5280, 4.2.1.1 // RFC 5280, 4.2.1.1
var a authKeyId var a authKeyId
...@@ -1011,18 +1059,19 @@ func reverseBitsInAByte(in byte) byte { ...@@ -1011,18 +1059,19 @@ func reverseBitsInAByte(in byte) byte {
} }
var ( var (
oidExtensionSubjectKeyId = []int{2, 5, 29, 14} oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
oidExtensionKeyUsage = []int{2, 5, 29, 15} oidExtensionKeyUsage = []int{2, 5, 29, 15}
oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37} oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37}
oidExtensionAuthorityKeyId = []int{2, 5, 29, 35} oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
oidExtensionBasicConstraints = []int{2, 5, 29, 19} oidExtensionBasicConstraints = []int{2, 5, 29, 19}
oidExtensionSubjectAltName = []int{2, 5, 29, 17} oidExtensionSubjectAltName = []int{2, 5, 29, 17}
oidExtensionCertificatePolicies = []int{2, 5, 29, 32} oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
oidExtensionNameConstraints = []int{2, 5, 29, 30} oidExtensionNameConstraints = []int{2, 5, 29, 30}
oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31}
) )
func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { 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 n := 0
if template.KeyUsage != 0 { if template.KeyUsage != 0 {
...@@ -1147,6 +1196,28 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { ...@@ -1147,6 +1196,28 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++ 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 // Adding another extension here? Remember to update the maximum number
// of elements in the make() at the top of the function. // of elements in the make() at the top of the function.
......
...@@ -336,6 +336,8 @@ func TestCreateSelfSignedCertificate(t *testing.T) { ...@@ -336,6 +336,8 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}}, PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
PermittedDNSDomains: []string{".example.com", "example.com"}, 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) derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv)
...@@ -386,6 +388,10 @@ func TestCreateSelfSignedCertificate(t *testing.T) { ...@@ -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) 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 { if test.checkSig {
err = cert.CheckSignatureFrom(cert) err = cert.CheckSignatureFrom(cert)
if err != nil { if err != nil {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment