1
0
mirror of https://github.com/golang/go synced 2024-11-25 02:07:58 -07:00

crypto/x509: Use ExtKeyUsage and UnknownExtKeyUsage fields from template in CreateCertificate

R=golang-dev, agl
CC=golang-dev
https://golang.org/cl/6535057
This commit is contained in:
Andrew Harding 2012-09-20 12:36:37 -04:00 committed by Adam Langley
parent be11889ab1
commit c993ac11bc
2 changed files with 79 additions and 25 deletions

View File

@ -389,6 +389,41 @@ const (
ExtKeyUsageOCSPSigning ExtKeyUsageOCSPSigning
) )
// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID.
var extKeyUsageOIDs = []struct {
extKeyUsage ExtKeyUsage
oid asn1.ObjectIdentifier
}{
{ExtKeyUsageAny, oidExtKeyUsageAny},
{ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth},
{ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth},
{ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning},
{ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection},
{ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem},
{ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel},
{ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser},
{ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping},
{ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning},
}
func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) {
for _, pair := range extKeyUsageOIDs {
if oid.Equal(pair.oid) {
return pair.extKeyUsage, true
}
}
return
}
func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) {
for _, pair := range extKeyUsageOIDs {
if eku == pair.extKeyUsage {
return pair.oid, true
}
}
return
}
// A Certificate represents an X.509 certificate. // A Certificate represents an X.509 certificate.
type Certificate struct { type Certificate struct {
Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature). Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
@ -865,28 +900,9 @@ func parseCertificate(in *certificate) (*Certificate, error) {
} }
for _, u := range keyUsage { for _, u := range keyUsage {
switch { if extKeyUsage, ok := extKeyUsageFromOID(u); ok {
case u.Equal(oidExtKeyUsageAny): out.ExtKeyUsage = append(out.ExtKeyUsage, extKeyUsage)
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageAny) } else {
case u.Equal(oidExtKeyUsageServerAuth):
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageServerAuth)
case u.Equal(oidExtKeyUsageClientAuth):
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageClientAuth)
case u.Equal(oidExtKeyUsageCodeSigning):
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageCodeSigning)
case u.Equal(oidExtKeyUsageEmailProtection):
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageEmailProtection)
case u.Equal(oidExtKeyUsageIPSECEndSystem):
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageIPSECEndSystem)
case u.Equal(oidExtKeyUsageIPSECTunnel):
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageIPSECTunnel)
case u.Equal(oidExtKeyUsageIPSECUser):
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageIPSECUser)
case u.Equal(oidExtKeyUsageTimeStamping):
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageTimeStamping)
case u.Equal(oidExtKeyUsageOCSPSigning):
out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageOCSPSigning)
default:
out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u) out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u)
} }
} }
@ -975,6 +991,7 @@ 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}
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}
@ -983,7 +1000,7 @@ var (
) )
func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
ret = make([]pkix.Extension, 7 /* maximum number of elements. */) ret = make([]pkix.Extension, 8 /* maximum number of elements. */)
n := 0 n := 0
if template.KeyUsage != 0 { if template.KeyUsage != 0 {
@ -1006,6 +1023,27 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++ n++
} }
if len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0 {
ret[n].Id = oidExtensionExtendedKeyUsage
var oids []asn1.ObjectIdentifier
for _, u := range template.ExtKeyUsage {
if oid, ok := oidFromExtKeyUsage(u); ok {
oids = append(oids, oid)
} else {
panic("internal error")
}
}
oids = append(oids, template.UnknownExtKeyUsage...)
ret[n].Value, err = asn1.Marshal(oids)
if err != nil {
return
}
n++
}
if template.BasicConstraintsValid { if template.BasicConstraintsValid {
ret[n].Id = oidExtensionBasicConstraints ret[n].Id = oidExtensionBasicConstraints
ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, template.MaxPathLen}) ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, template.MaxPathLen})
@ -1092,8 +1130,9 @@ func subjectBytes(cert *Certificate) ([]byte, error) {
// CreateCertificate creates a new certificate based on a template. The // CreateCertificate creates a new certificate based on a template. The
// following members of template are used: SerialNumber, Subject, NotBefore, // following members of template are used: SerialNumber, Subject, NotBefore,
// NotAfter, KeyUsage, BasicConstraintsValid, IsCA, MaxPathLen, SubjectKeyId, // NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid,
// DNSNames, PermittedDNSDomainsCritical, PermittedDNSDomains. // IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
// PermittedDNSDomains.
// //
// The certificate is signed by parent. If parent is equal to template then the // The certificate is signed by parent. If parent is equal to template then the
// certificate is self-signed. The parameter pub is the public key of the // certificate is self-signed. The parameter pub is the public key of the

View File

@ -19,6 +19,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/pem" "encoding/pem"
"math/big" "math/big"
"reflect"
"testing" "testing"
"time" "time"
) )
@ -262,6 +263,9 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
{"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true}, {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true},
} }
testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{3, 2, 1}}
for _, test := range tests { for _, test := range tests {
commonName := "test.example.com" commonName := "test.example.com"
template := Certificate{ template := Certificate{
@ -276,6 +280,9 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
SubjectKeyId: []byte{1, 2, 3, 4}, SubjectKeyId: []byte{1, 2, 3, 4},
KeyUsage: KeyUsageCertSign, KeyUsage: KeyUsageCertSign,
ExtKeyUsage: testExtKeyUsage,
UnknownExtKeyUsage: testUnknownExtKeyUsage,
BasicConstraintsValid: true, BasicConstraintsValid: true,
IsCA: true, IsCA: true,
DNSNames: []string{"test.example.com"}, DNSNames: []string{"test.example.com"},
@ -312,6 +319,14 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName) t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName)
} }
if !reflect.DeepEqual(cert.ExtKeyUsage, testExtKeyUsage) {
t.Errorf("%s: extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.ExtKeyUsage, testExtKeyUsage)
}
if !reflect.DeepEqual(cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) {
t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage)
}
if test.checkSig { if test.checkSig {
err = cert.CheckSignatureFrom(cert) err = cert.CheckSignatureFrom(cert)
if err != nil { if err != nil {