| // Copyright 2026 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| //go:build fips140v1.0 |
| |
| package x509 |
| |
| import "testing" |
| |
| // TestParseMLDSACertificateFIPS140v1_0 verifies that ML-DSA certificates can |
| // still be parsed under the FIPS 140-3 module v1.0.0, which doesn't support |
| // ML-DSA. The parsed certificate has PublicKeyAlgorithm set to |
| // UnknownPublicKeyAlgorithm and a nil PublicKey, so callers can inspect the |
| // rest of the certificate without erroring. |
| func TestParseMLDSACertificateFIPS140v1_0(t *testing.T) { |
| for _, tt := range []struct { |
| name string |
| pem string |
| }{ |
| {"ML-DSA-44", rfc9881ExampleCertificateMLDSA44}, |
| {"ML-DSA-65", rfc9881ExampleCertificateMLDSA65}, |
| {"ML-DSA-87", rfc9881ExampleCertificateMLDSA87}, |
| } { |
| t.Run(tt.name, func(t *testing.T) { |
| cert, err := ParseCertificate(pemDecode(t, tt.pem)) |
| if err != nil { |
| t.Fatalf("ParseCertificate failed: %v", err) |
| } |
| if cert.PublicKeyAlgorithm != UnknownPublicKeyAlgorithm { |
| t.Errorf("PublicKeyAlgorithm = %v, want UnknownPublicKeyAlgorithm", cert.PublicKeyAlgorithm) |
| } |
| if cert.PublicKey != nil { |
| t.Errorf("PublicKey = %v, want nil", cert.PublicKey) |
| } |
| // The rest of the certificate should still be inspectable. |
| if cert.Subject.CommonName == "" { |
| t.Error("Subject.CommonName is empty; expected the certificate to be parsed") |
| } |
| }) |
| } |
| } |
| |
| // TestMLDSAUnavailableErrorsNotPanics asserts that the public x509 entry |
| // points return errors (rather than panicking) when ML-DSA is unavailable. |
| // The mldsa package documents that "methods are unreachable" on v1.0.0; this |
| // test ensures x509 callers stay on the error path. |
| func TestMLDSAUnavailableErrorsNotPanics(t *testing.T) { |
| // ParsePKIXPublicKey: extracts the raw SPKI from a parsed cert and parses |
| // the public key directly. Should return an error, not panic. |
| cert, err := ParseCertificate(pemDecode(t, rfc9881ExampleCertificateMLDSA44)) |
| if err != nil { |
| t.Fatalf("ParseCertificate failed: %v", err) |
| } |
| if _, err := ParsePKIXPublicKey(cert.RawSubjectPublicKeyInfo); err == nil { |
| t.Error("ParsePKIXPublicKey: expected error, got nil") |
| } |
| // ParsePKCS8PrivateKey: ML-DSA seed-only private keys. |
| for _, tt := range []struct { |
| name string |
| pem string |
| }{ |
| {"ML-DSA-44", rfc9881ExamplePrivateKeyMLDSA44}, |
| {"ML-DSA-65", rfc9881ExamplePrivateKeyMLDSA65}, |
| {"ML-DSA-87", rfc9881ExamplePrivateKeyMLDSA87}, |
| } { |
| t.Run(tt.name, func(t *testing.T) { |
| if _, err := ParsePKCS8PrivateKey(pemDecode(t, tt.pem)); err == nil { |
| t.Error("ParsePKCS8PrivateKey: expected error, got nil") |
| } |
| }) |
| } |
| } |