return nil
}
-func buildExtensions(template *Certificate, authorityKeyId []byte) (ret []pkix.Extension, err error) {
+func buildExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId []byte) (ret []pkix.Extension, err error) {
ret = make([]pkix.Extension, 10 /* maximum number of elements. */)
n := 0
if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) &&
!oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {
ret[n].Id = oidExtensionSubjectAltName
+ // https://tools.ietf.org/html/rfc5280#section-4.2.1.6
+ // “If the subject field contains an empty sequence ... then
+ // subjectAltName extension ... is marked as critical”
+ ret[n].Critical = subjectIsEmpty
ret[n].Value, err = marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs)
if err != nil {
return
return
}
+// emptyASN1Subject is the ASN.1 DER encoding of an empty Subject, which is
+// just an empty SEQUENCE.
+var emptyASN1Subject = []byte{0x30, 0}
+
// CreateCertificate creates a new certificate based on a template.
// The following members of template are used: AuthorityKeyId,
// BasicConstraintsValid, DNSNames, ExcludedDNSDomains, ExtKeyUsage,
authorityKeyId = parent.SubjectKeyId
}
- extensions, err := buildExtensions(template, authorityKeyId)
+ extensions, err := buildExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId)
if err != nil {
return
}
t.Errorf("%s: ExtraNames didn't override Country", test.name)
}
+ for _, ext := range cert.Extensions {
+ if ext.Id.Equal(oidExtensionSubjectAltName) {
+ if ext.Critical {
+ t.Fatal("SAN extension is marked critical")
+ }
+ }
+ }
+
found := false
for _, atv := range cert.Subject.Names {
if atv.Type.Equal([]int{2, 5, 4, 42}) {
t.Fatalf("failed to parse certificate: %s", err)
}
}
+
+func TestEmptySubject(t *testing.T) {
+ template := Certificate{
+ SerialNumber: big.NewInt(1),
+ DNSNames: []string{"example.com"},
+ }
+
+ derBytes, err := CreateCertificate(rand.Reader, &template, &template, &testPrivateKey.PublicKey, testPrivateKey)
+ if err != nil {
+ t.Fatalf("failed to create certificate: %s", err)
+ }
+
+ cert, err := ParseCertificate(derBytes)
+ if err != nil {
+ t.Fatalf("failed to parse certificate: %s", err)
+ }
+
+ for _, ext := range cert.Extensions {
+ if ext.Id.Equal(oidExtensionSubjectAltName) {
+ if !ext.Critical {
+ t.Fatal("SAN extension is not critical")
+ }
+ return
+ }
+ }
+
+ t.Fatal("SAN extension is missing")
+}