Commit e74dcbeb authored by Adam Langley's avatar Adam Langley

crypto/x509: keep the raw Subject and Issuer.

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