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:
parent
be11889ab1
commit
c993ac11bc
@ -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
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user