]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/x509: keep the raw Subject and Issuer.
authorAdam Langley <agl@golang.org>
Fri, 14 Oct 2011 19:06:54 +0000 (15:06 -0400)
committerAdam Langley <agl@golang.org>
Fri, 14 Oct 2011 19:06:54 +0000 (15:06 -0400)
X509 names, like everything else X509, are ludicrously general. This
change keeps the raw version of the subject and issuer around for
matching. Since certificates use a distinguished encoding, comparing
the encoding is the same as comparing the values directly. This came
up recently when parsing the NSS built-in certificates which use the
raw subject and issuer for matching trust records to certificates.

R=bradfitz
CC=golang-dev
https://golang.org/cl/5275047

src/pkg/asn1/marshal.go
src/pkg/crypto/x509/cert_pool.go
src/pkg/crypto/x509/pkix/pkix.go
src/pkg/crypto/x509/verify_test.go
src/pkg/crypto/x509/x509.go

index d7eb63bf82c9f1531f4ae617086276b771a5540d..6d1f78bcc10b13fbbde55cf31ae64913bed3d911 100644 (file)
@@ -464,11 +464,15 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 
        if v.Type() == rawValueType {
                rv := v.Interface().(RawValue)
-               err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
-               if err != nil {
-                       return
+               if len(rv.FullBytes) != 0 {
+                       _, err = out.Write(rv.FullBytes)
+               } else {
+                       err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
+                       if err != nil {
+                               return
+                       }
+                       _, err = out.Write(rv.Bytes)
                }
-               _, err = out.Write(rv.Bytes)
                return
        }
 
index 16cd92efc3be71e76cfd4eee18f535bdb6ec0ff6..b9196ed46ed8fb9b028ae30bda8b09ec63e91ff4 100644 (file)
@@ -5,9 +5,7 @@
 package x509
 
 import (
-       "crypto/x509/pkix"
        "encoding/pem"
-       "strings"
 )
 
 // Roots is a set of certificates.
@@ -26,10 +24,6 @@ func NewCertPool() *CertPool {
        }
 }
 
-func nameToKey(name *pkix.Name) string {
-       return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
-}
-
 // findVerifiedParents attempts to find certificates in s which have signed the
 // given certificate. If no such certificate can be found or the signature
 // doesn't match, it returns nil.
@@ -40,7 +34,7 @@ func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
                candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
        }
        if len(candidates) == 0 {
-               candidates = s.byName[nameToKey(&cert.Issuer)]
+               candidates = s.byName[string(cert.RawIssuer)]
        }
 
        for _, c := range candidates {
@@ -72,7 +66,7 @@ func (s *CertPool) AddCert(cert *Certificate) {
                keyId := string(cert.SubjectKeyId)
                s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
        }
-       name := nameToKey(&cert.Subject)
+       name := string(cert.RawSubject)
        s.byName[name] = append(s.byName[name], n)
 }
 
index 266fd557a52c98af090341b5a7c6e10ea35dc9be..332a39462120a3a8b114cab77c24e18f2ad245de 100644 (file)
@@ -43,6 +43,8 @@ type Name struct {
        Locality, Province                        []string
        StreetAddress, PostalCode                 []string
        SerialNumber, CommonName                  string
+
+       Names []AttributeTypeAndValue
 }
 
 func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
@@ -51,6 +53,7 @@ func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
                        continue
                }
                atv := rdn[0]
+               n.Names = append(n.Names, atv)
                value, ok := atv.Value.(string)
                if !ok {
                        continue
index ecff7ffd810c2dce88346ca0fbfec5c5e172237a..eaa8169b0da7341a601b38f27f658370c6540f4d 100644 (file)
@@ -5,6 +5,7 @@
 package x509
 
 import (
+       "crypto/x509/pkix"
        "encoding/pem"
        "os"
        "strings"
@@ -211,6 +212,10 @@ func chainToDebugString(chain []*Certificate) string {
        return chainStr
 }
 
+func nameToKey(name *pkix.Name) string {
+       return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
+}
+
 const verisignRoot = `-----BEGIN CERTIFICATE-----
 MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
 A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
index 8fda4715927ad02251227ab0ee4ddec79528dcd9..5e08df752a2f68e66008c3ab7d4429e6b5c88586 100644 (file)
@@ -138,9 +138,9 @@ type tbsCertificate struct {
        Version            int `asn1:"optional,explicit,default:1,tag:0"`
        SerialNumber       *big.Int
        SignatureAlgorithm pkix.AlgorithmIdentifier
-       Issuer             pkix.RDNSequence
+       Issuer             asn1.RawValue
        Validity           validity
-       Subject            pkix.RDNSequence
+       Subject            asn1.RawValue
        PublicKey          publicKeyInfo
        UniqueId           asn1.BitString   `asn1:"optional,tag:1"`
        SubjectUniqueId    asn1.BitString   `asn1:"optional,tag:2"`
@@ -339,6 +339,8 @@ type Certificate struct {
        Raw                     []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
        RawTBSCertificate       []byte // Certificate part of raw ASN.1 DER content.
        RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
+       RawSubject              []byte // DER encoded Subject
+       RawIssuer               []byte // DER encoded Issuer
 
        Signature          []byte
        SignatureAlgorithm SignatureAlgorithm
@@ -556,6 +558,8 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
        out.Raw = in.Raw
        out.RawTBSCertificate = in.TBSCertificate.Raw
        out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw
+       out.RawSubject = in.TBSCertificate.Subject.FullBytes
+       out.RawIssuer = in.TBSCertificate.Issuer.FullBytes
 
        out.Signature = in.SignatureValue.RightAlign()
        out.SignatureAlgorithm =
@@ -575,8 +579,18 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
 
        out.Version = in.TBSCertificate.Version + 1
        out.SerialNumber = in.TBSCertificate.SerialNumber
-       out.Issuer.FillFromRDNSequence(&in.TBSCertificate.Issuer)
-       out.Subject.FillFromRDNSequence(&in.TBSCertificate.Subject)
+
+       var issuer, subject pkix.RDNSequence
+       if _, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil {
+               return nil, err
+       }
+       if _, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil {
+               return nil, err
+       }
+
+       out.Issuer.FillFromRDNSequence(&issuer)
+       out.Subject.FillFromRDNSequence(&subject)
+
        out.NotBefore = in.TBSCertificate.Validity.NotBefore
        out.NotAfter = in.TBSCertificate.Validity.NotAfter
 
@@ -968,14 +982,23 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
                return
        }
 
+       asn1Issuer, err := asn1.Marshal(parent.Issuer.ToRDNSequence())
+       if err != nil {
+               return
+       }
+       asn1Subject, err := asn1.Marshal(parent.Subject.ToRDNSequence())
+       if err != nil {
+               return
+       }
+
        encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
        c := tbsCertificate{
                Version:            2,
                SerialNumber:       template.SerialNumber,
                SignatureAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
-               Issuer:             parent.Subject.ToRDNSequence(),
+               Issuer:             asn1.RawValue{FullBytes: asn1Issuer},
                Validity:           validity{template.NotBefore, template.NotAfter},
-               Subject:            template.Subject.ToRDNSequence(),
+               Subject:            asn1.RawValue{FullBytes: asn1Subject},
                PublicKey:          publicKeyInfo{nil, pkix.AlgorithmIdentifier{Algorithm: oidRSA}, encodedPublicKey},
                Extensions:         extensions,
        }