mirror of
https://github.com/golang/go
synced 2024-11-22 00:54:43 -07:00
crypto/x509: policy OID support and fixes.
* Add support for certificate policy identifiers * Fix the version number of generated certificates * Fix the parsing of version numbers * Fix the case of multiple name entries (it should have been a list of tagged values, not a tagged list of values). R=r CC=golang-dev https://golang.org/cl/3044041
This commit is contained in:
parent
86630fe6ad
commit
ffa9000b75
@ -217,50 +217,40 @@ var (
|
||||
oidPostalCode = []int{2, 5, 4, 17}
|
||||
)
|
||||
|
||||
// appendRDNs appends a relativeDistinguishedNameSET to the given rdnSequence
|
||||
// and returns the new value. The relativeDistinguishedNameSET contains an
|
||||
// attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
|
||||
// search for AttributeTypeAndValue.
|
||||
func appendRDNs(in rdnSequence, values []string, oid asn1.ObjectIdentifier) rdnSequence {
|
||||
if len(values) == 0 {
|
||||
return in
|
||||
}
|
||||
|
||||
s := make([]attributeTypeAndValue, len(values))
|
||||
for i, value := range values {
|
||||
s[i].Type = oid
|
||||
s[i].Value = value
|
||||
}
|
||||
|
||||
return append(in, s)
|
||||
}
|
||||
|
||||
func (n Name) toRDNSequence() (ret rdnSequence) {
|
||||
ret = make([]relativeDistinguishedNameSET, 9 /* maximum number of elements */ )
|
||||
i := 0
|
||||
if len(n.Country) > 0 {
|
||||
ret[i] = []attributeTypeAndValue{{oidCountry, n.Country}}
|
||||
i++
|
||||
}
|
||||
if len(n.Organization) > 0 {
|
||||
ret[i] = []attributeTypeAndValue{{oidOrganization, n.Organization}}
|
||||
i++
|
||||
}
|
||||
if len(n.OrganizationalUnit) > 0 {
|
||||
ret[i] = []attributeTypeAndValue{{oidOrganizationalUnit, n.OrganizationalUnit}}
|
||||
i++
|
||||
}
|
||||
ret = appendRDNs(ret, n.Country, oidCountry)
|
||||
ret = appendRDNs(ret, n.Organization, oidOrganization)
|
||||
ret = appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
|
||||
ret = appendRDNs(ret, n.Locality, oidLocatity)
|
||||
ret = appendRDNs(ret, n.Province, oidProvince)
|
||||
ret = appendRDNs(ret, n.StreetAddress, oidStreetAddress)
|
||||
ret = appendRDNs(ret, n.PostalCode, oidPostalCode)
|
||||
if len(n.CommonName) > 0 {
|
||||
ret[i] = []attributeTypeAndValue{{oidCommonName, n.CommonName}}
|
||||
i++
|
||||
ret = appendRDNs(ret, []string{n.CommonName}, oidCommonName)
|
||||
}
|
||||
if len(n.SerialNumber) > 0 {
|
||||
ret[i] = []attributeTypeAndValue{{oidSerialNumber, n.SerialNumber}}
|
||||
i++
|
||||
}
|
||||
if len(n.Locality) > 0 {
|
||||
ret[i] = []attributeTypeAndValue{{oidLocatity, n.Locality}}
|
||||
i++
|
||||
}
|
||||
if len(n.Province) > 0 {
|
||||
ret[i] = []attributeTypeAndValue{{oidProvince, n.Province}}
|
||||
i++
|
||||
}
|
||||
if len(n.StreetAddress) > 0 {
|
||||
ret[i] = []attributeTypeAndValue{{oidStreetAddress, n.StreetAddress}}
|
||||
i++
|
||||
}
|
||||
if len(n.PostalCode) > 0 {
|
||||
ret[i] = []attributeTypeAndValue{{oidPostalCode, n.PostalCode}}
|
||||
i++
|
||||
ret = appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
|
||||
}
|
||||
|
||||
// Adding another RDN here? Remember to update the maximum number of
|
||||
// elements in the make() at the top of the function.
|
||||
|
||||
return ret[0:i]
|
||||
return ret
|
||||
}
|
||||
|
||||
func getSignatureAlgorithmFromOID(oid []int) SignatureAlgorithm {
|
||||
@ -339,6 +329,8 @@ type Certificate struct {
|
||||
// Subject Alternate Name values
|
||||
DNSNames []string
|
||||
EmailAddresses []string
|
||||
|
||||
PolicyIdentifiers []asn1.ObjectIdentifier
|
||||
}
|
||||
|
||||
// UnsupportedAlgorithmError results from attempting to perform an operation
|
||||
@ -476,6 +468,12 @@ type rsaPublicKey struct {
|
||||
E int
|
||||
}
|
||||
|
||||
// RFC 5280 4.2.1.4
|
||||
type policyInformation struct {
|
||||
Policy asn1.ObjectIdentifier
|
||||
// policyQualifiers omitted
|
||||
}
|
||||
|
||||
func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.Error) {
|
||||
switch algo {
|
||||
case RSA:
|
||||
@ -517,7 +515,7 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.Version = in.TBSCertificate.Version
|
||||
out.Version = in.TBSCertificate.Version + 1
|
||||
out.SerialNumber = in.TBSCertificate.SerialNumber.Bytes
|
||||
out.Issuer.fillFromRDNSequence(&in.TBSCertificate.Issuer)
|
||||
out.Subject.fillFromRDNSequence(&in.TBSCertificate.Subject)
|
||||
@ -623,6 +621,17 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
|
||||
}
|
||||
out.SubjectKeyId = keyid
|
||||
continue
|
||||
|
||||
case 32:
|
||||
// RFC 5280 4.2.1.4: Certificate Policies
|
||||
var policies []policyInformation
|
||||
if _, err = asn1.Unmarshal(e.Value, &policies); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies))
|
||||
for i, policy := range policies {
|
||||
out.PolicyIdentifiers[i] = policy.Policy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,10 +697,11 @@ var (
|
||||
oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
|
||||
oidExtensionBasicConstraints = []int{2, 5, 29, 19}
|
||||
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
|
||||
oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
|
||||
)
|
||||
|
||||
func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
|
||||
ret = make([]extension, 5 /* maximum number of elements. */ )
|
||||
ret = make([]extension, 6 /* maximum number of elements. */ )
|
||||
n := 0
|
||||
|
||||
if template.KeyUsage != 0 {
|
||||
@ -755,6 +765,19 @@ func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
|
||||
n++
|
||||
}
|
||||
|
||||
if len(template.PolicyIdentifiers) > 0 {
|
||||
ret[n].Id = oidExtensionCertificatePolicies
|
||||
policies := make([]policyInformation, len(template.PolicyIdentifiers))
|
||||
for i, policy := range template.PolicyIdentifiers {
|
||||
policies[i].Policy = policy
|
||||
}
|
||||
ret[n].Value, err = asn1.Marshal(policies)
|
||||
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.
|
||||
|
||||
@ -796,7 +819,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
|
||||
|
||||
encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
|
||||
c := tbsCertificate{
|
||||
Version: 3,
|
||||
Version: 2,
|
||||
SerialNumber: asn1.RawValue{Bytes: template.SerialNumber, Tag: 2},
|
||||
SignatureAlgorithm: algorithmIdentifier{oidSHA1WithRSA},
|
||||
Issuer: parent.Subject.toRDNSequence(),
|
||||
|
@ -5,6 +5,7 @@
|
||||
package x509
|
||||
|
||||
import (
|
||||
"asn1"
|
||||
"big"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
@ -169,6 +170,8 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
DNSNames: []string{"test.example.com"},
|
||||
|
||||
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
|
||||
}
|
||||
|
||||
derBytes, err := CreateCertificate(random, &template, &template, &priv.PublicKey, priv)
|
||||
@ -182,6 +185,11 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
|
||||
t.Errorf("Failed to parse certificate: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
|
||||
t.Errorf("Failed to parse policy identifiers: got:%#v want:%#v", cert.PolicyIdentifiers, template.PolicyIdentifiers)
|
||||
}
|
||||
|
||||
err = cert.CheckSignatureFrom(cert)
|
||||
if err != nil {
|
||||
t.Errorf("Signature verification failed: %s", err)
|
||||
|
Loading…
Reference in New Issue
Block a user