Fix for duplicate SANs in signed certificates (#16700)

* Fix for duplicate SANs in signed certificates when othernames are present in the CSR SAN extension and UseCSRValues is true.

When UseCSRValues is true (as is the case on the sign-verbatim endpoint), all extensions including Subject Alternative Names are copied from the CSR to the final certificate.
If the Subject Alternative Name in question contains any othernames (such as a Microsoft UPN) the SAN extension is added again as a workaround for an encoding issue (in function HandleOtherSANs).
Having duplicate x509v3 extensions is invalid and is rejected by openssl on Ubuntu 20.04, and also by Go since https://github.com/golang/go/issues/50988 (including in Go 1.19).

In this fix I do not add the extension from the CSR if it will be added during HandleOtherSANs.

* Added unittest and changelog entry.
This commit is contained in:
Ruben De Visscher 2022-10-07 18:19:08 +02:00 committed by GitHub
parent 39c7e7c191
commit 1f0cf558a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 2 deletions

View File

@ -2131,10 +2131,21 @@ func runTestSignVerbatim(t *testing.T, keyType string) {
if err != nil {
t.Fatal(err)
}
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
csrReq := &x509.CertificateRequest{
Subject: pkix.Name{
CommonName: "foo.bar.com",
},
// Check that otherName extensions are not duplicated (see hashicorp/vault#16700).
// If these extensions are duplicated, sign-verbatim will fail when parsing the signed certificate on Go 1.19+ (see golang/go#50988).
// On older versions of Go this test will fail due to an explicit check for duplicate otherNames later in this test.
ExtraExtensions: []pkix.Extension{
{
Id: oidExtensionSubjectAltName,
Critical: false,
Value: []byte{0x30, 0x26, 0xA0, 0x24, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03, 0xA0, 0x16, 0x0C, 0x14, 0x75, 0x73, 0x65, 0x72, 0x6E, 0x61, 0x6D, 0x65, 0x40, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x2E, 0x63, 0x6F, 0x6D},
},
},
}
csr, err := x509.CreateCertificateRequest(rand.Reader, csrReq, key)
if err != nil {
@ -2285,6 +2296,19 @@ func runTestSignVerbatim(t *testing.T, keyType string) {
t.Fatalf("expected a single cert, got %d", len(certs))
}
cert = certs[0]
// Fallback check for duplicate otherName, necessary on Go versions before 1.19.
// We assume that there is only one SAN in the original CSR and that it is an otherName.
san_count := 0
for _, ext := range cert.Extensions {
if ext.Id.Equal(oidExtensionSubjectAltName) {
san_count += 1
}
}
if san_count != 1 {
t.Fatalf("expected one SAN extension, got %d", san_count)
}
notAfter := cert.NotAfter.Format(time.RFC3339)
if notAfter != "9999-12-31T23:59:59Z" {
t.Fatal(fmt.Errorf("not after from certificate is not matching with input parameter"))

3
changelog/16700.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
secrets/pki: Fixes duplicate otherName in certificates created by the sign-verbatim endpoint.
```

View File

@ -1033,7 +1033,10 @@ func selectSignatureAlgorithmForECDSA(pub crypto.PublicKey, signatureBits int) x
}
}
var oidExtensionBasicConstraints = []int{2, 5, 29, 19}
var (
oidExtensionBasicConstraints = []int{2, 5, 29, 19}
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
)
// CreateCSR creates a CSR with the default rand.Reader to
// generate a cert/keypair. This is currently only meant
@ -1208,7 +1211,7 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun
certTemplate.URIs = data.CSR.URIs
for _, name := range data.CSR.Extensions {
if !name.Id.Equal(oidExtensionBasicConstraints) {
if !name.Id.Equal(oidExtensionBasicConstraints) && !(len(data.Params.OtherSANs) > 0 && name.Id.Equal(oidExtensionSubjectAltName)) {
certTemplate.ExtraExtensions = append(certTemplate.ExtraExtensions, name)
}
}