go: crypto/x509: gate marshaling of Policies on a GODEBUG [freeze exception]
#60665 introduced a new OID type and a new field on the Certificate.
This change might cause a slight backwards compatibility breakage, it was not discussed there, so it might be worth discussing it here again.
Consider https://go.dev/play/p/Z92_1DOZJQi?v=gotip
func TestParsedCertificateAsTemplate(t *testing.T) {
b, _ := pem.Decode([]byte(largeOIDPEM))
if b == nil {
t.Fatalf("couldn't decode test certificate")
}
template, err := x509.ParseCertificate(b.Bytes)
if err != nil {
t.Fatalf("ParseCertificate unexpected error: %v", err)
}
template.PublicKey = nil
// Clear all PolicyIdentifiers from template.
template.PolicyIdentifiers = nil
newCertDER, err := x509.CreateCertificate(rand.Reader, template, template, rsaPrivateKey.Public(), rsaPrivateKey)
if err != nil {
t.Fatalf("CreateCertificate unexpected error: %v", err)
}
cert, err := x509.ParseCertificate(newCertDER)
if err != nil {
t.Fatalf("ParseCertificate unexpected error: %v", err)
}
if len(cert.PolicyIdentifiers) != 0 {
t.Fatalf("PolicyIdentifiers field is not empty") // fails on gotip
}
}
This does not fail on go 1.21, but on gotip it fails. I am not sure whether we should be concerned about this. Not sure whether (and why) someone might be using a parsed certificate as a template, but who knows.
About this issue
- Original URL
- State: closed
- Created 7 months ago
- Comments: 29 (27 by maintainers)
Yup that is still an issue. I think any approach we take here (that migrates from one field to another) is going to exhibit a degree of this problem.
@rsc suggested taking the GODEBUG approach, which I think is a viable solution. We’d gate which field is marshaled behind a GODEBUG, i.e. x509marshalpolicies, and would only use one of the two fields, depending on the value of the GODEBUG. We can then change the default value at some point in the future, and anything using the
go
directive in their go.mod file will retain the old behavior, and will only have to change code when they update the directive (which is the acceptable breakage path for GODEBUGs).I’ll prepare two changes, one which removes the dual marshaling behavior, and another which gates which field is marshaled using a GODEBUG. We can submit the first one to get back to the “safe” behavior before 1.22RC1, and if we get this through the proposal/release-exception review in time for the 1.22RC1, we can submit that.