mirror of
https://github.com/golang/go.git
synced 2026-06-27 19:30:52 +00:00
crypto/tls: add ML-DSA support
Tested against Google Chrome Canary 150.0.7834.0. The Client-TLSv10, Client-TLSv11, and Client-TLSv12 recordings need to change because they are configured with a version range that includes TLS 1.3 (even if the OpenSSL server selects the lower one), so they include ML-DSA signature algorithms in the Client Hello. The Client-TLSv13 and Server-TLSv13-ClientAuthRequested* recordings need to change because they now advertise ML-DSA support. Because of #79481, we need to regenerate all recordings anyway, so defer doing so to the next CL 779662, to avoid churning twice and bloating the git history. Fixes #78888 Change-Id: I14e6a89b459166155261aa8fc0edb83c6a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/776709 Reviewed-by: Roland Shoemaker <roland@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> TryBot-Bypass: Filippo Valsorda <filippo@golang.org> Auto-Submit: Filippo Valsorda <filippo@golang.org>
This commit is contained in:
parent
003833a138
commit
c74ba7d265
24 changed files with 1060 additions and 61 deletions
|
|
@ -6,3 +6,9 @@ pkg crypto/x509, const MLDSA65 = 18 #78888
|
|||
pkg crypto/x509, const MLDSA65 SignatureAlgorithm #78888
|
||||
pkg crypto/x509, const MLDSA87 = 19 #78888
|
||||
pkg crypto/x509, const MLDSA87 SignatureAlgorithm #78888
|
||||
pkg crypto/tls, const MLDSA44 = 2308 #78888
|
||||
pkg crypto/tls, const MLDSA44 SignatureScheme #78888
|
||||
pkg crypto/tls, const MLDSA65 = 2309 #78888
|
||||
pkg crypto/tls, const MLDSA65 SignatureScheme #78888
|
||||
pkg crypto/tls, const MLDSA87 = 2310 #78888
|
||||
pkg crypto/tls, const MLDSA87 SignatureScheme #78888
|
||||
|
|
|
|||
|
|
@ -6,3 +6,6 @@ The new [crypto/mldsa] package implements the post-quantum ML-DSA signature
|
|||
scheme specified in FIPS 204.
|
||||
|
||||
[crypto/x509] now supports ML-DSA private keys, public keys, and signatures.
|
||||
|
||||
[crypto/tls] now supports ML-DSA signatures in TLS 1.3, with the new
|
||||
[MLDSA44], [MLDSA65], and [MLDSA87] [SignatureScheme] values.
|
||||
|
|
|
|||
1
doc/next/6-stdlib/99-minor/crypto/tls/78888.md
Normal file
1
doc/next/6-stdlib/99-minor/crypto/tls/78888.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
<!-- crypto/tls ML-DSA support is documented in doc/next/6-stdlib/70-mldsa.md. -->
|
||||
|
|
@ -289,9 +289,8 @@ bXVL8iKLrG91IYQByUHZIn3WVAd2bfi4MfKagRt0ggd4
|
|||
expectNoErr(t, err)
|
||||
expectNoErr(t, errRet2(kem.NewPrivateKey(kb)))
|
||||
expectNoErr(t, errRet2(kem.NewPublicKey(k.PublicKey().Bytes())))
|
||||
if fips140.Version() == "v1.0.0" {
|
||||
t.Skip("FIPS 140-3 Module v1.0.0 does not provide HPKE GCM modes")
|
||||
}
|
||||
// HPKE GCM modes were added in v1.26.0.
|
||||
cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.26.0")
|
||||
c, err := hpke.Seal(k.PublicKey(), hpke.HKDFSHA256(), hpke.AES128GCM(), nil, nil)
|
||||
expectNoErr(t, err)
|
||||
_, err = hpke.Open(k, hpke.HKDFSHA256(), hpke.AES128GCM(), nil, c)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/mldsa"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -45,6 +46,14 @@ func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc c
|
|||
if !ed25519.Verify(pubKey, signed, sig) {
|
||||
return errors.New("Ed25519 verification failure")
|
||||
}
|
||||
case signatureMLDSA:
|
||||
pubKey, ok := pubkey.(*mldsa.PublicKey)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected an ML-DSA public key, got %T", pubkey)
|
||||
}
|
||||
if err := mldsa.Verify(pubKey, signed, sig, nil); err != nil {
|
||||
return fmt.Errorf("ML-DSA verification failure: %w", err)
|
||||
}
|
||||
case signaturePKCS1v15:
|
||||
pubKey, ok := pubkey.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
|
|
@ -133,6 +142,8 @@ func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType
|
|||
sigType = signatureECDSA
|
||||
case Ed25519:
|
||||
sigType = signatureEd25519
|
||||
case MLDSA44, MLDSA65, MLDSA87:
|
||||
sigType = signatureMLDSA
|
||||
default:
|
||||
return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm)
|
||||
}
|
||||
|
|
@ -147,6 +158,8 @@ func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType
|
|||
hash = crypto.SHA512
|
||||
case Ed25519:
|
||||
hash = directSigning
|
||||
case MLDSA44, MLDSA65, MLDSA87:
|
||||
hash = directSigning
|
||||
default:
|
||||
return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm)
|
||||
}
|
||||
|
|
@ -168,6 +181,8 @@ func legacyTypeAndHashFromPublicKey(pub crypto.PublicKey) (sigType uint8, hash c
|
|||
// full signature, and not even OpenSSL bothers with the
|
||||
// complexity, so we can't even test it properly.
|
||||
return 0, 0, fmt.Errorf("tls: Ed25519 public keys are not supported before TLS 1.2")
|
||||
case *mldsa.PublicKey:
|
||||
return 0, 0, fmt.Errorf("tls: ML-DSA public keys are not supported before TLS 1.3")
|
||||
default:
|
||||
return 0, 0, fmt.Errorf("tls: unsupported public key: %T", pub)
|
||||
}
|
||||
|
|
@ -224,6 +239,17 @@ func signatureSchemesForPublicKey(version uint16, pub crypto.PublicKey) []Signat
|
|||
return sigAlgs
|
||||
case ed25519.PublicKey:
|
||||
return []SignatureScheme{Ed25519}
|
||||
case *mldsa.PublicKey:
|
||||
switch pub.Parameters() {
|
||||
case mldsa.MLDSA44():
|
||||
return []SignatureScheme{MLDSA44}
|
||||
case mldsa.MLDSA65():
|
||||
return []SignatureScheme{MLDSA65}
|
||||
case mldsa.MLDSA87():
|
||||
return []SignatureScheme{MLDSA87}
|
||||
default:
|
||||
panic("tls: internal error: unknown ML-DSA parameter set: " + pub.Parameters().String())
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
|
@ -300,6 +326,8 @@ func unsupportedCertificateError(cert *Certificate) error {
|
|||
case *rsa.PublicKey:
|
||||
return fmt.Errorf("tls: certificate RSA key size too small for supported signature algorithms")
|
||||
case ed25519.PublicKey:
|
||||
case *mldsa.PublicKey:
|
||||
return errors.New("tls: ML-DSA certificates require TLS 1.3")
|
||||
default:
|
||||
return fmt.Errorf("tls: unsupported certificate key (%T)", pub)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ package tls
|
|||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/fips140"
|
||||
"crypto/internal/cryptotest"
|
||||
"crypto/mldsa"
|
||||
"crypto/tls/internal/fips140tls"
|
||||
"internal/testenv"
|
||||
"strconv"
|
||||
|
|
@ -39,6 +42,9 @@ func TestSignatureSelection(t *testing.T) {
|
|||
{testECDSAP256Cert, []SignatureScheme{ECDSAWithP256AndSHA256}, VersionTLS13, "", ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256},
|
||||
{testEd25519Cert, []SignatureScheme{Ed25519}, VersionTLS12, "", Ed25519, signatureEd25519, directSigning},
|
||||
{testEd25519Cert, []SignatureScheme{Ed25519}, VersionTLS13, "", Ed25519, signatureEd25519, directSigning},
|
||||
{testMLDSA44Cert, []SignatureScheme{MLDSA44}, VersionTLS13, "", MLDSA44, signatureMLDSA, directSigning},
|
||||
{testMLDSA65Cert, []SignatureScheme{MLDSA65}, VersionTLS13, "", MLDSA65, signatureMLDSA, directSigning},
|
||||
{testMLDSA87Cert, []SignatureScheme{MLDSA87}, VersionTLS13, "", MLDSA87, signatureMLDSA, directSigning},
|
||||
|
||||
// TLS 1.2 without signature_algorithms extension
|
||||
{testRSA2048Cert, nil, VersionTLS12, "tlssha1=1", PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1},
|
||||
|
|
@ -53,6 +59,10 @@ func TestSignatureSelection(t *testing.T) {
|
|||
if fips140tls.Required() && test.expectedHash == crypto.SHA1 {
|
||||
t.Skip("skipping test not compatible with TLS FIPS mode")
|
||||
}
|
||||
switch test.expectedSigAlg {
|
||||
case MLDSA44, MLDSA65, MLDSA87:
|
||||
cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.26.0")
|
||||
}
|
||||
if test.godebug != "" {
|
||||
testenv.SetGODEBUG(t, test.godebug)
|
||||
} else {
|
||||
|
|
@ -115,6 +125,18 @@ func TestSignatureSelection(t *testing.T) {
|
|||
{testECDSAP256Cert, []SignatureScheme{ECDSAWithSHA1}, VersionTLS12},
|
||||
{testRSA2048Cert, nil, VersionTLS12},
|
||||
{testECDSAP256Cert, nil, VersionTLS12},
|
||||
// ML-DSA requires TLS 1.3.
|
||||
{testMLDSA44Cert, []SignatureScheme{MLDSA44}, VersionTLS12},
|
||||
{testMLDSA65Cert, []SignatureScheme{MLDSA65}, VersionTLS12},
|
||||
{testMLDSA87Cert, []SignatureScheme{MLDSA87}, VersionTLS12},
|
||||
// ML-DSA parameter sets don't cross-match.
|
||||
{testMLDSA44Cert, []SignatureScheme{MLDSA65}, VersionTLS13},
|
||||
{testMLDSA65Cert, []SignatureScheme{MLDSA87}, VersionTLS13},
|
||||
{testMLDSA87Cert, []SignatureScheme{MLDSA44}, VersionTLS13},
|
||||
// ML-DSA cert with non-ML-DSA peer sig algs and vice versa.
|
||||
{testMLDSA44Cert, []SignatureScheme{Ed25519}, VersionTLS13},
|
||||
{testRSA2048Cert, []SignatureScheme{MLDSA44}, VersionTLS13},
|
||||
{testECDSAP256Cert, []SignatureScheme{MLDSA44}, VersionTLS13},
|
||||
}
|
||||
|
||||
for testNo, test := range badTests {
|
||||
|
|
@ -153,12 +175,24 @@ func TestLegacyTypeAndHash(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Errorf("Ed25519: unexpected success")
|
||||
}
|
||||
|
||||
// ML-DSA is not supported by TLS 1.0 and 1.1. Skip under FIPS 140-3 module
|
||||
// v1.0.0 which doesn't support ML-DSA public keys.
|
||||
if fips140.Version() != "v1.0.0" {
|
||||
for _, key := range []*mldsa.PrivateKey{
|
||||
testMLDSA44Key, testMLDSA65Key, testMLDSA87Key,
|
||||
} {
|
||||
if _, _, err := legacyTypeAndHashFromPublicKey(key.PublicKey()); err == nil {
|
||||
t.Errorf("%s: unexpected success", key.PublicKey().Parameters())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestSupportedSignatureAlgorithms checks that all supportedSignatureAlgorithms
|
||||
// have valid type and hash information.
|
||||
func TestSupportedSignatureAlgorithms(t *testing.T) {
|
||||
for _, sigAlg := range supportedSignatureAlgorithms(VersionTLS12) {
|
||||
for _, sigAlg := range supportedSignatureAlgorithms(VersionTLS12, VersionTLS13) {
|
||||
sigType, hash, err := typeAndHashFromSignatureScheme(sigAlg)
|
||||
if err != nil {
|
||||
t.Errorf("%v: unexpected error: %v", sigAlg, err)
|
||||
|
|
@ -166,7 +200,7 @@ func TestSupportedSignatureAlgorithms(t *testing.T) {
|
|||
if sigType == 0 {
|
||||
t.Errorf("%v: missing signature type", sigAlg)
|
||||
}
|
||||
if hash == 0 && sigAlg != Ed25519 {
|
||||
if hash == 0 && sigAlg != Ed25519 && sigAlg != MLDSA44 && sigAlg != MLDSA65 && sigAlg != MLDSA87 {
|
||||
t.Errorf("%v: missing hash", sigAlg)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/fips140"
|
||||
icryptotest "crypto/internal/cryptotest"
|
||||
"crypto/mldsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
|
|
@ -32,12 +33,10 @@ var generate = flag.Bool("generate", false, "regenerate certificates_test.go")
|
|||
|
||||
func TestGenerateCertificates(t *testing.T) {
|
||||
testenv.MustHaveSource(t)
|
||||
icryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.26.0")
|
||||
if testing.Short() && !*generate {
|
||||
t.Skip("set -generate to regenerate certificates_test.go, or run without -short to check")
|
||||
}
|
||||
if fips140.Version() == "v1.0.0" {
|
||||
t.Skip("FIPS 140-3 module v1.0.0 doesn't support SetGlobalRandom")
|
||||
}
|
||||
|
||||
// Allow RSA keys below 1024 bits for testRSA512.
|
||||
testenv.SetGODEBUG(t, "rsa1024min=0")
|
||||
|
|
@ -313,6 +312,78 @@ func TestGenerateCertificates(t *testing.T) {
|
|||
}
|
||||
emit("testClientRSAPSS", "RSA 2048 client leaf, SAN=test.golang.example, issued by Client Root.\n\t// Signature algorithm is SHA512WithRSAPSS (rsaEncryption SPKI, rsassaPss signature).", der, clientRSAPSSKey)
|
||||
|
||||
// ML-DSA-44.
|
||||
mldsa44Key, err := mldsa.GenerateKey(mldsa.MLDSA44())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpl = serverLeaf("ML-DSA-44", "test.golang.example")
|
||||
der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, mldsa44Key.PublicKey(), rootKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
emit("testMLDSA44", "ML-DSA-44 server leaf, SAN=test.golang.example, issued by Root.", der, mldsa44Key)
|
||||
|
||||
// ML-DSA-65.
|
||||
mldsa65Key, err := mldsa.GenerateKey(mldsa.MLDSA65())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpl = serverLeaf("ML-DSA-65", "test.golang.example")
|
||||
der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, mldsa65Key.PublicKey(), rootKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
emit("testMLDSA65", "ML-DSA-65 server leaf, SAN=test.golang.example, issued by Root.", der, mldsa65Key)
|
||||
|
||||
// ML-DSA-87.
|
||||
mldsa87Key, err := mldsa.GenerateKey(mldsa.MLDSA87())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpl = serverLeaf("ML-DSA-87", "test.golang.example")
|
||||
der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, mldsa87Key.PublicKey(), rootKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
emit("testMLDSA87", "ML-DSA-87 server leaf, SAN=test.golang.example, issued by Root.", der, mldsa87Key)
|
||||
|
||||
// Client ML-DSA-44.
|
||||
clientMLDSA44Key, err := mldsa.GenerateKey(mldsa.MLDSA44())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpl = clientLeaf("clientAuth ML-DSA-44", "test.golang.example")
|
||||
der, err = x509.CreateCertificate(rand.Reader, tmpl, clientRootCert, clientMLDSA44Key.PublicKey(), clientRootKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
emit("testClientMLDSA44", "ML-DSA-44 client leaf, SAN=test.golang.example, issued by Client Root.", der, clientMLDSA44Key)
|
||||
|
||||
// Client ML-DSA-65.
|
||||
clientMLDSA65Key, err := mldsa.GenerateKey(mldsa.MLDSA65())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpl = clientLeaf("clientAuth ML-DSA-65", "test.golang.example")
|
||||
der, err = x509.CreateCertificate(rand.Reader, tmpl, clientRootCert, clientMLDSA65Key.PublicKey(), clientRootKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
emit("testClientMLDSA65", "ML-DSA-65 client leaf, SAN=test.golang.example, issued by Client Root.", der, clientMLDSA65Key)
|
||||
|
||||
// Client ML-DSA-87.
|
||||
clientMLDSA87Key, err := mldsa.GenerateKey(mldsa.MLDSA87())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpl = clientLeaf("clientAuth ML-DSA-87", "test.golang.example")
|
||||
der, err = x509.CreateCertificate(rand.Reader, tmpl, clientRootCert, clientMLDSA87Key.PublicKey(), clientRootKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
emit("testClientMLDSA87", "ML-DSA-87 client leaf, SAN=test.golang.example, issued by Client Root.", der, clientMLDSA87Key)
|
||||
|
||||
// Generate certificates_test.go.
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprint(&buf, `// Code generated by certificates_generator_test.go; DO NOT EDIT.
|
||||
|
|
@ -323,8 +394,10 @@ package tls
|
|||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/mldsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
)
|
||||
|
||||
`)
|
||||
|
|
@ -335,8 +408,16 @@ import (
|
|||
fmt.Fprintf(&buf, "\t// %s\n", p.comment)
|
||||
fmt.Fprintf(&buf, "\t%sCert = parseTestCert(%sCertPEM, %sKeyPEM)\n",
|
||||
p.name, p.name, p.name)
|
||||
fmt.Fprintf(&buf, "\t%sKey = %sCert.PrivateKey.(%s)\n\n",
|
||||
p.name, p.name, p.keyType)
|
||||
// ML-DSA is unavailable in FIPS 140-3 module v1.0.0; the cert
|
||||
// loads with a nil PrivateKey under that module, so use a tolerant
|
||||
// type assertion. Tests using these vars must skip on v1.0.0.
|
||||
if p.keyType == "*mldsa.PrivateKey" {
|
||||
fmt.Fprintf(&buf, "\t%sKey, _ = %sCert.PrivateKey.(%s)\n\n",
|
||||
p.name, p.name, p.keyType)
|
||||
} else {
|
||||
fmt.Fprintf(&buf, "\t%sKey = %sCert.PrivateKey.(%s)\n\n",
|
||||
p.name, p.name, p.keyType)
|
||||
}
|
||||
}
|
||||
fmt.Fprint(&buf, ` // x509.CertPool containing testRootCert.
|
||||
testRootCertPool = newTestCertPool(testRootCertPEM)
|
||||
|
|
@ -352,11 +433,28 @@ import (
|
|||
}
|
||||
|
||||
fmt.Fprint(&buf, `func parseTestCert(certPEM, keyPEM string) Certificate {
|
||||
tlsCert, err := X509KeyPair([]byte(certPEM), []byte(testingKey(keyPEM)))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
var cert Certificate
|
||||
block, _ := pem.Decode([]byte(certPEM))
|
||||
if block == nil {
|
||||
panic("failed to parse certificate PEM")
|
||||
}
|
||||
return tlsCert
|
||||
cert.Certificate = [][]byte{block.Bytes}
|
||||
cert.Leaf, _ = x509.ParseCertificate(block.Bytes)
|
||||
if cert.Leaf == nil {
|
||||
panic("failed to parse certificate")
|
||||
}
|
||||
// Don't parse the private key for ML-DSA certificates with FIPS 140-3 module v1.0.0.
|
||||
if cert.Leaf.PublicKeyAlgorithm != x509.UnknownPublicKeyAlgorithm {
|
||||
block, _ = pem.Decode([]byte(keyPEM))
|
||||
if block == nil {
|
||||
panic("failed to parse key PEM")
|
||||
}
|
||||
cert.PrivateKey, _ = x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||
if cert.PrivateKey == nil {
|
||||
panic("failed to parse private key")
|
||||
}
|
||||
}
|
||||
return cert
|
||||
}
|
||||
|
||||
func newTestCertPool(certPEM string) *x509.CertPool {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@ package tls
|
|||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/mldsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -75,6 +77,30 @@ var (
|
|||
testClientRSAPSSCert = parseTestCert(testClientRSAPSSCertPEM, testClientRSAPSSKeyPEM)
|
||||
testClientRSAPSSKey = testClientRSAPSSCert.PrivateKey.(*rsa.PrivateKey)
|
||||
|
||||
// ML-DSA-44 server leaf, SAN=test.golang.example, issued by Root.
|
||||
testMLDSA44Cert = parseTestCert(testMLDSA44CertPEM, testMLDSA44KeyPEM)
|
||||
testMLDSA44Key, _ = testMLDSA44Cert.PrivateKey.(*mldsa.PrivateKey)
|
||||
|
||||
// ML-DSA-65 server leaf, SAN=test.golang.example, issued by Root.
|
||||
testMLDSA65Cert = parseTestCert(testMLDSA65CertPEM, testMLDSA65KeyPEM)
|
||||
testMLDSA65Key, _ = testMLDSA65Cert.PrivateKey.(*mldsa.PrivateKey)
|
||||
|
||||
// ML-DSA-87 server leaf, SAN=test.golang.example, issued by Root.
|
||||
testMLDSA87Cert = parseTestCert(testMLDSA87CertPEM, testMLDSA87KeyPEM)
|
||||
testMLDSA87Key, _ = testMLDSA87Cert.PrivateKey.(*mldsa.PrivateKey)
|
||||
|
||||
// ML-DSA-44 client leaf, SAN=test.golang.example, issued by Client Root.
|
||||
testClientMLDSA44Cert = parseTestCert(testClientMLDSA44CertPEM, testClientMLDSA44KeyPEM)
|
||||
testClientMLDSA44Key, _ = testClientMLDSA44Cert.PrivateKey.(*mldsa.PrivateKey)
|
||||
|
||||
// ML-DSA-65 client leaf, SAN=test.golang.example, issued by Client Root.
|
||||
testClientMLDSA65Cert = parseTestCert(testClientMLDSA65CertPEM, testClientMLDSA65KeyPEM)
|
||||
testClientMLDSA65Key, _ = testClientMLDSA65Cert.PrivateKey.(*mldsa.PrivateKey)
|
||||
|
||||
// ML-DSA-87 client leaf, SAN=test.golang.example, issued by Client Root.
|
||||
testClientMLDSA87Cert = parseTestCert(testClientMLDSA87CertPEM, testClientMLDSA87KeyPEM)
|
||||
testClientMLDSA87Key, _ = testClientMLDSA87Cert.PrivateKey.(*mldsa.PrivateKey)
|
||||
|
||||
// x509.CertPool containing testRootCert.
|
||||
testRootCertPool = newTestCertPool(testRootCertPEM)
|
||||
// x509.CertPool containing testClientRootCert.
|
||||
|
|
@ -621,12 +647,402 @@ jxrfmmrMaIXhnSWAXeBn6Gz+VAgRhfiZpP5/4YS8rPV1d8pOfuQGuP+zDmke1nLC
|
|||
sZpT/jzJuZsUkbuLREQbZGQ=
|
||||
-----END TESTING KEY-----`
|
||||
|
||||
const testMLDSA44CertPEM = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
5oYWLUWYOf4=
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const testMLDSA44KeyPEM = `
|
||||
-----BEGIN TESTING KEY-----
|
||||
MDQCAQAwCwYJYIZIAWUDBAMRBCKAIKjca7do6h6TzowpEdGGuG0qv0TIYdgnqV2S
|
||||
Mcvu+n6A
|
||||
-----END TESTING KEY-----`
|
||||
|
||||
const testMLDSA65CertPEM = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
3xQD501vTZeBE/2Z+9u5jR78I8z9oijS
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const testMLDSA65KeyPEM = `
|
||||
-----BEGIN TESTING KEY-----
|
||||
MDQCAQAwCwYJYIZIAWUDBAMSBCKAIEEEYHBN/doadMzAAyaqjdxoQDKDiGb+9tKn
|
||||
xCTHrLlF
|
||||
-----END TESTING KEY-----`
|
||||
|
||||
const testMLDSA87CertPEM = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const testMLDSA87KeyPEM = `
|
||||
-----BEGIN TESTING KEY-----
|
||||
MDQCAQAwCwYJYIZIAWUDBAMTBCKAIF21EV0gObGfCvdWN+cM+pRH0lPg1qU2VLip
|
||||
r0TYx5dY
|
||||
-----END TESTING KEY-----`
|
||||
|
||||
const testClientMLDSA44CertPEM = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIHNjCCBh6gAwIBAgIBEzANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDEwtDbGll
|
||||
bnQgUm9vdDAeFw0xNjA3MTIxNzMyMDlaFw0xNzAxMjgxNzMyMDlaMB8xHTAbBgNV
|
||||
BAMTFGNsaWVudEF1dGggTUwtRFNBLTQ0MIIFMjALBglghkgBZQMEAxEDggUhANFe
|
||||
IirktYDm5K+DKrsSgDwtwrx6rbN25WxaN+ufIWdV3HA9zTnfDVVWz47ng4m7mrGs
|
||||
zClJW0G0RGsVlHgVrCy28ipAZCtILJShvvXLzKUc6UF3jtHz5Sh2GeMwfOBcFBu7
|
||||
+jExzdGK589TM2k3tsiXN/EGeq1/eMUQOz+8fN9XbPxLQthcXOU6imu0xYYssr0J
|
||||
Jcu94dCthprYqCTqg1oZRMm1Nq4v81g4sJ2IcYZZ0zMHy6yqSuVFK11+Pe7oxXyd
|
||||
BNLhrAs4+y835ZrLoVpDoYyzJKoMnbMeO9hP/NL8rVAkmpVECkfbHLvbHkwiptDx
|
||||
e2L4W4GbiuHb2TqSkxrfhU21SRpnJD673fx8/V00Awl7FjOJYuuhjqnCGISPXrMx
|
||||
h9Zpgfck1VV+zAz1PNAo6JMXx1ule0aUbsn54JqawkJz1Yi/tBTyXjSYK5BPpv8t
|
||||
xeAC51yteSrPkJz9rcOhR6bpwxKfpp1ht/Mcyohddf33eKpaLWDDdIs3Po5ScrfK
|
||||
5OjpWV19OLiRh695xiUqammfKoJ9aL1g+X9LCJ3+bR/r0B3v0/qcWTJKpkWTJzhx
|
||||
8HnBMbDKXDJrKTR6tXq2UBB5oQIjgAWXykuamCmuJa43Sh2egZpNIC9A8VctSngS
|
||||
KIUhze36v17wUsShBzTeG1YUv31qA+1mZMp3X7J41bkN6OL2+A6bQlw6aH9qdg2Z
|
||||
r71ByF+XmRKQYxPr9x2aGKoQeeX5739x0d6uLqKOLQs4NhIWgT7Mre16EbwYoXJS
|
||||
o77MTIbh1O2ZkAWPRmyDetH1vefl+C36KI1X3Pot7Ns3SKz0wr/iW9Tn3OkrNh7n
|
||||
bAN0qkz+9+9dTH+rwyX4YseptVax7sBdMnNyTQc7Y3JKdfGOhoGmyVkzPjIbkddm
|
||||
GRIDp+3PR3HrjpODuuJv5urzuM0ko1qZzTIda0TQRURkEdwYyOu5CjxCsWZQVuqw
|
||||
nYBFgf58KcKdnSE284LiTy3+CYauGzsHT772zr1Nry6z0QZuFCie12Lwb0DhrZK2
|
||||
uhOC/LNz0v6vjCbymWl24v9+r/iwri/JlT/vxO3LUz5Uj93pJqcaXaaD2GVMBoZf
|
||||
gAePSpMxwxJzBG1CNGlnrI3odpyfhYZ8kQkHf2PEv6+KVHXHUYPRQeh2JqiXr75K
|
||||
s8LCjykXFCCzhJ6fQZDH609S0MPItotzspxX0a7es2VzuyTkSp1CTOwK9WISyilb
|
||||
rh8XrA6sEta0YkjE6kaEN+KCdJGKm2hl86PSXRgl9x9fxUibW2cT16ESIYDTu4kg
|
||||
QR92icnRrun18lZJJWXB8E6kgzG+ia5lil/RxuPsGD1omu6pFH2cfY4qISSlvbFp
|
||||
kbS6dhVNxG1PLPdBqYX6VPq1KdRbtStS6LLEHdPMPm6F4r3YEwo6uAmqmQiZwrZ+
|
||||
65+/Y0HusVn6tgGJqKeW4xaD/o50nq37SuhV1ov5kJGBCUgzlPSRKg6ZhWx5zKVN
|
||||
34rClzpdOYv9Gva8x4YmCN9w6z9bJP10mJ3GEklMmEvlhJIV6Op08MkBjRQoI0+V
|
||||
vJPkgFTMiGAuuAOxhmDYXixfg8mBNuDog0/qjOUERnnpFC0/s0RcI5aspcQn0dBQ
|
||||
mKhuBTEAlvWsN5tMZfQ8Xk5kKvpntWYQCP3wD68GIH7DPLSXwipIiwmOrsMlRh4i
|
||||
mi6Qu4FlrQjP+ejeovSuY7yJoxAq0WuRQmkryO/+LzpZMs4bshDgkFHmvzBQNiFV
|
||||
la7mC6w02xHzD0y2JYGjdjB0MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggr
|
||||
BgEFBQcDAjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFBFzbkcYXaYhGhtMYSY5
|
||||
yPte6XQkMB4GA1UdEQQXMBWCE3Rlc3QuZ29sYW5nLmV4YW1wbGUwDQYJKoZIhvcN
|
||||
AQELBQADggEBAKzJDzcNZ7qg/jLYMUk0u6Tcfm9p4MuQVH59UT3rI5oZTOF9EAxt
|
||||
Zi0ErX7XUR1z0LHOYFu0x49iJarSl5ZAQfmrOjLKINNeHAr2Lj4pdM89aWO3PVUU
|
||||
qT/8OwzOFbHixHjHMmeAIZyt33Aa3pQKZOozSsnaYAos7BpmPZ9gW3iI6e+lEOwB
|
||||
VU4aMx7GvsS0OxqH++WhaZQ00F/ESUHGZLE1PJhIm67h8lTfK0lOxDuXnqDC6qvT
|
||||
dGs41I8JbauDQqTuWAIa5YEsR71B0nOUS+FL4ZGim1QDbx+AQbgbobpXpZjN9gCw
|
||||
TKUtVXxH5czj31ZMuAYfycdf/sdfvprjxcI=
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const testClientMLDSA44KeyPEM = `
|
||||
-----BEGIN TESTING KEY-----
|
||||
MDQCAQAwCwYJYIZIAWUDBAMRBCKAIHdJoEDI6UeYdZ2U21l0ep3akAB7qA+mLAWX
|
||||
cufwhk2g
|
||||
-----END TESTING KEY-----`
|
||||
|
||||
const testClientMLDSA65CertPEM = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const testClientMLDSA65KeyPEM = `
|
||||
-----BEGIN TESTING KEY-----
|
||||
MDQCAQAwCwYJYIZIAWUDBAMSBCKAIOtV+uJia3QCimf1E6NpjLFdNFvp5eQCjjJO
|
||||
JA04aNQw
|
||||
-----END TESTING KEY-----`
|
||||
|
||||
const testClientMLDSA87CertPEM = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
kRkrThM7W3DA2kiSqdCkJsV6VoTf8TPwykHdXPdyASbOAlbWCQMizHShTdOYkRtb
|
||||
LbaaSAepumRi0Gr/pOhj7YVDX2eBfkinn2Alof2FGZYQ1YIm7vEA55NizLc8/zaB
|
||||
QqPcw8qJw+5Dxu8dpu53vmT5868PXw0qsiF3TQLFUbAmtebTOS4rcmYEkpUXq3Kc
|
||||
jSNlNgYdcPS4qZZNPwCSFnK9xa3HJY1B/nQdis24zz+haicIA7EH2QP3vzmeOxov
|
||||
v+6zeUtItCmmJj+Z3v7JMp5ic+H86pnSjeJxoyymymq34+f+KSc3IyX5ogm1ppY9
|
||||
THqbIHHyeP8mZf8WI9qihJ2bK0LvkbKN4kv7Qkay6CIbm8s8V218DvH0HESi5aN2
|
||||
MHQwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB
|
||||
/wQCMAAwHwYDVR0jBBgwFoAUEXNuRxhdpiEaG0xhJjnI+17pdCQwHgYDVR0RBBcw
|
||||
FYITdGVzdC5nb2xhbmcuZXhhbXBsZTANBgkqhkiG9w0BAQsFAAOCAQEAaqe3/b+W
|
||||
WOSWcvN1P7gb2JIDigcNvStq04GTItDmAFS3TFkSZryJ97cfW4HjYesrk+uNMDG4
|
||||
JsUT1I4pyEqIV4LaCAEzuWLRl4Mfi8aEgJWHzSTNBflmJnv1vZ1a/bbyXgYq4bCi
|
||||
+VlDVm2AJ4hBoEE6KuzZZRh84C/nl/nmuW/lRGynr8i2oatHCY73V3hGvZ0tcXpJ
|
||||
NwYUG4xDVhCk/U5aqeKJ/rI1odErvifSJYCCfqmDxE25pBL2Ci9FfQK8izPKrO/l
|
||||
NhZaZhuAYd/i+OqZK1BoiRs4xpVRhKRXol8ES2Hr+Sz+OhcX3xfrfY8DHyHp5rmW
|
||||
SV/Pw5w+PSi7tg==
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const testClientMLDSA87KeyPEM = `
|
||||
-----BEGIN TESTING KEY-----
|
||||
MDQCAQAwCwYJYIZIAWUDBAMTBCKAIJOInTmP6L2i2T7bVftiIR5OkrnZTSQLimAK
|
||||
NFW4io0J
|
||||
-----END TESTING KEY-----`
|
||||
|
||||
func parseTestCert(certPEM, keyPEM string) Certificate {
|
||||
tlsCert, err := X509KeyPair([]byte(certPEM), []byte(testingKey(keyPEM)))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
var cert Certificate
|
||||
block, _ := pem.Decode([]byte(certPEM))
|
||||
if block == nil {
|
||||
panic("failed to parse certificate PEM")
|
||||
}
|
||||
return tlsCert
|
||||
cert.Certificate = [][]byte{block.Bytes}
|
||||
cert.Leaf, _ = x509.ParseCertificate(block.Bytes)
|
||||
if cert.Leaf == nil {
|
||||
panic("failed to parse certificate")
|
||||
}
|
||||
// Don't parse the private key for ML-DSA certificates with FIPS 140-3 module v1.0.0.
|
||||
if cert.Leaf.PublicKeyAlgorithm != x509.UnknownPublicKeyAlgorithm {
|
||||
block, _ = pem.Decode([]byte(keyPEM))
|
||||
if block == nil {
|
||||
panic("failed to parse key PEM")
|
||||
}
|
||||
cert.PrivateKey, _ = x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||
if cert.PrivateKey == nil {
|
||||
panic("failed to parse private key")
|
||||
}
|
||||
}
|
||||
return cert
|
||||
}
|
||||
|
||||
func newTestCertPool(certPEM string) *x509.CertPool {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/fips140"
|
||||
"crypto/mldsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha512"
|
||||
|
|
@ -216,11 +218,12 @@ const (
|
|||
signatureRSAPSS
|
||||
signatureECDSA
|
||||
signatureEd25519
|
||||
signatureMLDSA
|
||||
)
|
||||
|
||||
// directSigning is a standard Hash value that signals that no pre-hashing
|
||||
// should be performed, and that the input should be signed directly. It is the
|
||||
// hash function associated with the Ed25519 signature scheme.
|
||||
// hash function associated with the Ed25519 and ML-DSA signature schemes.
|
||||
var directSigning crypto.Hash = 0
|
||||
|
||||
// helloRetryRequestRandom is set as the Random value of a ServerHello
|
||||
|
|
@ -425,6 +428,11 @@ const (
|
|||
// EdDSA algorithms.
|
||||
Ed25519 SignatureScheme = 0x0807
|
||||
|
||||
// ML-DSA algorithms.
|
||||
MLDSA44 SignatureScheme = 0x0904
|
||||
MLDSA65 SignatureScheme = 0x0905
|
||||
MLDSA87 SignatureScheme = 0x0906
|
||||
|
||||
// Legacy signature and hash algorithms for TLS 1.2.
|
||||
PKCS1WithSHA1 SignatureScheme = 0x0201
|
||||
ECDSAWithSHA1 SignatureScheme = 0x0203
|
||||
|
|
@ -1486,6 +1494,9 @@ func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error {
|
|||
return errors.New("connection doesn't support Ed25519")
|
||||
}
|
||||
ecdsaCipherSuite = true
|
||||
case *mldsa.PublicKey:
|
||||
// ML-DSA requires TLS 1.3, which we already excluded above.
|
||||
return errors.New("connection doesn't support ML-DSA")
|
||||
case *rsa.PublicKey:
|
||||
default:
|
||||
return supportsRSAFallback(unsupportedCertificateError(c))
|
||||
|
|
@ -1610,8 +1621,8 @@ var writerMutex sync.Mutex
|
|||
type Certificate struct {
|
||||
Certificate [][]byte
|
||||
// PrivateKey contains the private key corresponding to the public key in
|
||||
// Leaf. This must implement [crypto.Signer] with an RSA, ECDSA or Ed25519
|
||||
// PublicKey.
|
||||
// Leaf. This must implement [crypto.Signer] with an RSA, ECDSA, Ed25519
|
||||
// (TLS 1.2+), or ML-DSA (TLS 1.3) PublicKey.
|
||||
//
|
||||
// For a server up to TLS 1.2, it can also implement crypto.Decrypter with
|
||||
// an RSA PublicKey.
|
||||
|
|
@ -1747,15 +1758,21 @@ func unexpectedMessageError(wanted, got any) error {
|
|||
var testingOnlySupportedSignatureAlgorithms []SignatureScheme
|
||||
|
||||
// supportedSignatureAlgorithms returns the supported signature algorithms for
|
||||
// the given minimum TLS version, to advertise in ClientHello and
|
||||
// CertificateRequest messages.
|
||||
func supportedSignatureAlgorithms(minVers uint16) []SignatureScheme {
|
||||
// the given range of TLS versions, to advertise in ClientHello and
|
||||
// CertificateRequest messages. An algorithm is included if it is enabled at any
|
||||
// version in the range.
|
||||
func supportedSignatureAlgorithms(minVers, maxVers uint16) []SignatureScheme {
|
||||
sigAlgs := defaultSupportedSignatureAlgorithms()
|
||||
if testingOnlySupportedSignatureAlgorithms != nil {
|
||||
sigAlgs = slices.Clone(testingOnlySupportedSignatureAlgorithms)
|
||||
}
|
||||
return slices.DeleteFunc(sigAlgs, func(s SignatureScheme) bool {
|
||||
return isDisabledSignatureAlgorithm(minVers, s, false)
|
||||
for v := minVers; v <= maxVers; v++ {
|
||||
if !isDisabledSignatureAlgorithm(v, s, false) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1766,6 +1783,18 @@ func isDisabledSignatureAlgorithm(version uint16, s SignatureScheme, isCert bool
|
|||
return true
|
||||
}
|
||||
|
||||
switch s {
|
||||
case MLDSA44, MLDSA65, MLDSA87:
|
||||
// ML-DSA is not available in FIPS 140-3 module v1.0.0.
|
||||
if fips140.Version() == "v1.0.0" {
|
||||
return true
|
||||
}
|
||||
// ML-DSA codepoints are only defined for TLS 1.3.
|
||||
if version < VersionTLS13 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// For the _cert extension we include all algorithms, including SHA-1 and
|
||||
// PKCS#1 v1.5, because it's more likely that something on our side will be
|
||||
// willing to accept a *-with-SHA1 certificate (e.g. with a custom
|
||||
|
|
@ -1795,10 +1824,15 @@ func isDisabledSignatureAlgorithm(version uint16, s SignatureScheme, isCert bool
|
|||
|
||||
// supportedSignatureAlgorithmsCert returns the supported algorithms for
|
||||
// signatures in certificates.
|
||||
func supportedSignatureAlgorithmsCert() []SignatureScheme {
|
||||
func supportedSignatureAlgorithmsCert(minVers, maxVers uint16) []SignatureScheme {
|
||||
sigAlgs := defaultSupportedSignatureAlgorithms()
|
||||
return slices.DeleteFunc(sigAlgs, func(s SignatureScheme) bool {
|
||||
return isDisabledSignatureAlgorithm(0, s, true)
|
||||
for v := minVers; v <= maxVers; v++ {
|
||||
if !isDisabledSignatureAlgorithm(v, s, true) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ func _() {
|
|||
_ = x[ECDSAWithP384AndSHA384-1283]
|
||||
_ = x[ECDSAWithP521AndSHA512-1539]
|
||||
_ = x[Ed25519-2055]
|
||||
_ = x[MLDSA44-2308]
|
||||
_ = x[MLDSA65-2309]
|
||||
_ = x[MLDSA87-2310]
|
||||
_ = x[PKCS1WithSHA1-513]
|
||||
_ = x[ECDSAWithSHA1-515]
|
||||
}
|
||||
|
|
@ -32,10 +35,12 @@ const (
|
|||
_SignatureScheme_name_6 = "PKCS1WithSHA512"
|
||||
_SignatureScheme_name_7 = "ECDSAWithP521AndSHA512"
|
||||
_SignatureScheme_name_8 = "PSSWithSHA256PSSWithSHA384PSSWithSHA512Ed25519"
|
||||
_SignatureScheme_name_9 = "MLDSA44MLDSA65MLDSA87"
|
||||
)
|
||||
|
||||
var (
|
||||
_SignatureScheme_index_8 = [...]uint8{0, 13, 26, 39, 46}
|
||||
_SignatureScheme_index_9 = [...]uint8{0, 7, 14, 21}
|
||||
)
|
||||
|
||||
func (i SignatureScheme) String() string {
|
||||
|
|
@ -59,6 +64,9 @@ func (i SignatureScheme) String() string {
|
|||
case 2052 <= i && i <= 2055:
|
||||
i -= 2052
|
||||
return _SignatureScheme_name_8[_SignatureScheme_index_8[i]:_SignatureScheme_index_8[i+1]]
|
||||
case 2308 <= i && i <= 2310:
|
||||
i -= 2308
|
||||
return _SignatureScheme_name_9[_SignatureScheme_index_9[i]:_SignatureScheme_index_9[i+1]]
|
||||
default:
|
||||
return "SignatureScheme(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
|
|
@ -117,8 +125,9 @@ const _ClientAuthType_name = "NoClientCertRequestClientCertRequireAnyClientCertV
|
|||
var _ClientAuthType_index = [...]uint8{0, 12, 29, 49, 72, 98}
|
||||
|
||||
func (i ClientAuthType) String() string {
|
||||
if i < 0 || i >= ClientAuthType(len(_ClientAuthType_index)-1) {
|
||||
idx := int(i) - 0
|
||||
if i < 0 || idx >= len(_ClientAuthType_index)-1 {
|
||||
return "ClientAuthType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _ClientAuthType_name[_ClientAuthType_index[i]:_ClientAuthType_index[i+1]]
|
||||
return _ClientAuthType_name[_ClientAuthType_index[idx]:_ClientAuthType_index[idx+1]]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ func defaultCurvePreferences() []CurveID {
|
|||
// Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc.
|
||||
func defaultSupportedSignatureAlgorithms() []SignatureScheme {
|
||||
return []SignatureScheme{
|
||||
MLDSA44,
|
||||
MLDSA65,
|
||||
MLDSA87,
|
||||
PSSWithSHA256,
|
||||
ECDSAWithP256AndSHA256,
|
||||
Ed25519,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/internal/boring"
|
||||
"crypto/mldsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
)
|
||||
|
|
@ -42,6 +44,9 @@ var (
|
|||
PSSWithSHA256,
|
||||
ECDSAWithP256AndSHA256,
|
||||
Ed25519,
|
||||
MLDSA44,
|
||||
MLDSA65,
|
||||
MLDSA87,
|
||||
PSSWithSHA384,
|
||||
PSSWithSHA512,
|
||||
PKCS1WithSHA256,
|
||||
|
|
@ -72,6 +77,9 @@ func isCertificateAllowedFIPS(c *x509.Certificate) bool {
|
|||
return k.Curve == elliptic.P256() || k.Curve == elliptic.P384() || k.Curve == elliptic.P521()
|
||||
case ed25519.PublicKey:
|
||||
return true
|
||||
case *mldsa.PublicKey:
|
||||
// Only for the native module.
|
||||
return !boring.Enabled
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"crypto/fips140"
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/cryptotest"
|
||||
"crypto/mldsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
|
|
@ -26,7 +27,7 @@ import (
|
|||
|
||||
var testConfigFIPS140 = &Config{
|
||||
Time: testTime,
|
||||
Certificates: []Certificate{testECDSAP256Cert, testRSAPSSCert, testEd25519Cert},
|
||||
Certificates: []Certificate{testECDSAP256Cert, testRSAPSSCert, testEd25519Cert, testMLDSA44Cert, testMLDSA65Cert, testMLDSA87Cert},
|
||||
RootCAs: testRootCertPool,
|
||||
ServerName: "test.golang.example",
|
||||
}
|
||||
|
|
@ -181,7 +182,7 @@ func isFIPSSignatureScheme(alg SignatureScheme) bool {
|
|||
PSSWithSHA384,
|
||||
PSSWithSHA512:
|
||||
return true
|
||||
case Ed25519:
|
||||
case Ed25519, MLDSA44, MLDSA65, MLDSA87:
|
||||
// Only for the native module.
|
||||
return !boring.Enabled
|
||||
case PKCS1WithSHA1, ECDSAWithSHA1:
|
||||
|
|
@ -283,11 +284,18 @@ func TestFIPSServerSignatureAndHash(t *testing.T) {
|
|||
|
||||
for _, sigHash := range defaultSupportedSignatureAlgorithms() {
|
||||
t.Run(fmt.Sprintf("%v", sigHash), func(t *testing.T) {
|
||||
isMLDSA := sigHash == MLDSA44 || sigHash == MLDSA65 || sigHash == MLDSA87
|
||||
if isMLDSA {
|
||||
cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.26.0")
|
||||
}
|
||||
serverConfig := testConfigFIPS140.Clone()
|
||||
testingOnlySupportedSignatureAlgorithms = []SignatureScheme{sigHash}
|
||||
// PKCS#1 v1.5 signature algorithms can't be used standalone in TLS
|
||||
// 1.3, and the ECDSA ones bind to the curve used.
|
||||
serverConfig.MaxVersion = VersionTLS12
|
||||
// 1.3, and the ECDSA ones bind to the curve used. However, ML-DSA
|
||||
// requires TLS 1.3.
|
||||
if !isMLDSA {
|
||||
serverConfig.MaxVersion = VersionTLS12
|
||||
}
|
||||
|
||||
runWithFIPSDisabled(t, func(t *testing.T) {
|
||||
clientErr, serverErr := fipsHandshake(t, testConfigFIPS140, serverConfig)
|
||||
|
|
@ -398,6 +406,15 @@ func TestFIPSCertAlgs(t *testing.T) {
|
|||
|
||||
L1_I := fipsCert(t, "L1_I", fipsECDSAKey(t, elliptic.P384()), I_R1, fipsCertLeaf|fipsCertFIPSOK)
|
||||
L2_I := fipsCert(t, "L2_I", fipsRSAKey(t, 1024), I_R1, fipsCertLeaf)
|
||||
var L3_I *fipsCertificate
|
||||
if fips140.Version() != "v1.0.0" {
|
||||
// ML-DSA is not implemented by the Go+BoringCrypto FIPS 140 module.
|
||||
mldsaFlags := fipsCertLeaf | fipsCertFIPSOK
|
||||
if boring.Enabled {
|
||||
mldsaFlags = fipsCertLeaf
|
||||
}
|
||||
L3_I = fipsCert(t, "L3_I", fipsMLDSAKey(t, mldsa.MLDSA44()), I_R1, mldsaFlags)
|
||||
}
|
||||
|
||||
// client verifying server cert
|
||||
testServerCert := func(t *testing.T, desc string, pool *x509.CertPool, key any, list [][]byte, ok bool) {
|
||||
|
|
@ -465,11 +482,19 @@ func TestFIPSCertAlgs(t *testing.T) {
|
|||
runWithFIPSDisabled(t, func(t *testing.T) {
|
||||
testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
|
||||
testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
|
||||
if L3_I != nil {
|
||||
testServerCert(t, "basic ML-DSA", r1pool, L3_I.key, [][]byte{L3_I.der, I_R1.der}, true)
|
||||
testClientCert(t, "basic ML-DSA (client cert)", r1pool, L3_I.key, [][]byte{L3_I.der, I_R1.der}, true)
|
||||
}
|
||||
})
|
||||
|
||||
runWithFIPSEnabled(t, func(t *testing.T) {
|
||||
testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
|
||||
testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
|
||||
if L3_I != nil {
|
||||
testServerCert(t, "basic ML-DSA (fips)", r1pool, L3_I.key, [][]byte{L3_I.der, I_R1.der}, L3_I.fipsOK)
|
||||
testClientCert(t, "basic ML-DSA (fips, client cert)", r1pool, L3_I.key, [][]byte{L3_I.der, I_R1.der}, L3_I.fipsOK)
|
||||
}
|
||||
})
|
||||
|
||||
if t.Failed() {
|
||||
|
|
@ -567,6 +592,14 @@ func fipsECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey {
|
|||
return k
|
||||
}
|
||||
|
||||
func fipsMLDSAKey(t *testing.T, params mldsa.Parameters) *mldsa.PrivateKey {
|
||||
k, err := mldsa.GenerateKey(params)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
type fipsCertificate struct {
|
||||
name string
|
||||
org string
|
||||
|
|
@ -622,6 +655,9 @@ func fipsCert(t *testing.T, name string, key any, parent *fipsCertificate, mode
|
|||
case *ecdsa.PrivateKey:
|
||||
pub = &k.PublicKey
|
||||
desc = "ECDSA-" + k.Curve.Params().Name
|
||||
case *mldsa.PrivateKey:
|
||||
pub = k.PublicKey()
|
||||
desc = k.PublicKey().Parameters().String()
|
||||
default:
|
||||
t.Fatalf("invalid key %T", key)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/mldsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
|
|
@ -35,6 +36,7 @@ var (
|
|||
rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set")
|
||||
ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521")
|
||||
ed25519Key = flag.Bool("ed25519", false, "Generate an Ed25519 key")
|
||||
mldsaKey = flag.Bool("mldsa", false, "Generate an ML-DSA-44 key")
|
||||
)
|
||||
|
||||
func publicKey(priv any) any {
|
||||
|
|
@ -45,6 +47,8 @@ func publicKey(priv any) any {
|
|||
return &k.PublicKey
|
||||
case ed25519.PrivateKey:
|
||||
return k.Public().(ed25519.PublicKey)
|
||||
case *mldsa.PrivateKey:
|
||||
return k.PublicKey()
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
|
@ -63,6 +67,8 @@ func main() {
|
|||
case "":
|
||||
if *ed25519Key {
|
||||
_, priv, err = ed25519.GenerateKey(rand.Reader)
|
||||
} else if *mldsaKey {
|
||||
priv, err = mldsa.GenerateKey(mldsa.MLDSA44())
|
||||
} else {
|
||||
priv, err = rsa.GenerateKey(rand.Reader, *rsaBits)
|
||||
}
|
||||
|
|
@ -81,8 +87,8 @@ func main() {
|
|||
log.Fatalf("Failed to generate private key: %v", err)
|
||||
}
|
||||
|
||||
// ECDSA, ED25519 and RSA subject keys should have the DigitalSignature
|
||||
// KeyUsage bits set in the x509.Certificate template
|
||||
// ECDSA, ED25519, ML-DSA, and RSA subject keys should have the
|
||||
// DigitalSignature KeyUsage bits set in the x509.Certificate template
|
||||
keyUsage := x509.KeyUsageDigitalSignature
|
||||
// Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In
|
||||
// the context of TLS this KeyUsage is particular to RSA key exchange and
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"crypto/ed25519"
|
||||
"crypto/hpke"
|
||||
"crypto/internal/fips140/tls13"
|
||||
"crypto/mldsa"
|
||||
"crypto/rsa"
|
||||
"crypto/subtle"
|
||||
"crypto/tls/internal/fips140tls"
|
||||
|
|
@ -119,8 +120,8 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCli
|
|||
}
|
||||
|
||||
if maxVersion >= VersionTLS12 {
|
||||
hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms(minVersion)
|
||||
hello.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithmsCert()
|
||||
hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms(minVersion, maxVersion)
|
||||
hello.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithmsCert(minVersion, maxVersion)
|
||||
}
|
||||
|
||||
var keyShareKeys *keySharePrivateKeys
|
||||
|
|
@ -1170,7 +1171,11 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
|
|||
|
||||
switch certs[0].PublicKey.(type) {
|
||||
case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
|
||||
break
|
||||
case *mldsa.PublicKey:
|
||||
if c.vers < VersionTLS13 {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return errors.New("tls: server's certificate uses ML-DSA, which requires TLS 1.3")
|
||||
}
|
||||
default:
|
||||
c.sendAlert(alertUnsupportedCertificate)
|
||||
return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error {
|
|||
// See RFC 8446, Section 4.4.3.
|
||||
// We don't use hs.hello.supportedSignatureAlgorithms because it might
|
||||
// include PKCS#1 v1.5 and SHA-1 if the ClientHello also supported TLS 1.2.
|
||||
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms(c.vers)) ||
|
||||
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms(c.vers, c.vers)) ||
|
||||
!isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, signatureSchemesForPublicKey(c.vers, c.peerCertificates[0].PublicKey)) {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return errors.New("tls: certificate used with invalid signature algorithm")
|
||||
|
|
|
|||
|
|
@ -179,10 +179,10 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
|||
}
|
||||
}
|
||||
if rand.Intn(10) > 5 {
|
||||
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS12)
|
||||
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS12, VersionTLS13)
|
||||
}
|
||||
if rand.Intn(10) > 5 {
|
||||
m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms(VersionTLS12)
|
||||
m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms(VersionTLS12, VersionTLS13)
|
||||
}
|
||||
for i := 0; i < rand.Intn(5); i++ {
|
||||
m.alpnProtocols = append(m.alpnProtocols, randomString(rand.Intn(20)+1, rand))
|
||||
|
|
@ -465,10 +465,10 @@ func (*certificateRequestMsgTLS13) Generate(rand *rand.Rand, size int) reflect.V
|
|||
m.scts = true
|
||||
}
|
||||
if rand.Intn(10) > 5 {
|
||||
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS12)
|
||||
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS12, VersionTLS13)
|
||||
}
|
||||
if rand.Intn(10) > 5 {
|
||||
m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms(VersionTLS12)
|
||||
m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms(VersionTLS12, VersionTLS13)
|
||||
}
|
||||
if rand.Intn(10) > 5 {
|
||||
m.certificateAuthorities = make([][]byte, 3)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/mldsa"
|
||||
"crypto/rsa"
|
||||
"crypto/subtle"
|
||||
"crypto/tls/internal/fips140tls"
|
||||
|
|
@ -310,6 +311,11 @@ func (hs *serverHandshakeState) processClientHello() error {
|
|||
hs.ecSignOk = true
|
||||
case *rsa.PublicKey:
|
||||
hs.rsaSignOk = true
|
||||
case *mldsa.PublicKey:
|
||||
// ML-DSA can only be used with TLS 1.3.
|
||||
c.sendAlert(alertInternalError)
|
||||
return fmt.Errorf("tls: ML-DSA certificates require TLS 1.3, but client negotiated %s",
|
||||
VersionName(c.vers))
|
||||
default:
|
||||
c.sendAlert(alertInternalError)
|
||||
return fmt.Errorf("tls: unsupported signing key type (%T)", priv.Public())
|
||||
|
|
@ -659,7 +665,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
|||
}
|
||||
if c.vers >= VersionTLS12 {
|
||||
certReq.hasSignatureAlgorithm = true
|
||||
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(c.vers)
|
||||
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(c.vers, c.vers)
|
||||
}
|
||||
|
||||
// An empty list of certificateAuthorities signals to
|
||||
|
|
@ -1002,6 +1008,11 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
|
|||
if len(certs) > 0 {
|
||||
switch certs[0].PublicKey.(type) {
|
||||
case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
|
||||
case *mldsa.PublicKey:
|
||||
if c.vers < VersionTLS13 {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return errors.New("tls: client certificate uses ML-DSA, which requires TLS 1.3")
|
||||
}
|
||||
default:
|
||||
c.sendAlert(alertUnsupportedCertificate)
|
||||
return fmt.Errorf("tls: client certificate contains an unsupported public key of type %T", certs[0].PublicKey)
|
||||
|
|
|
|||
|
|
@ -832,8 +832,8 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error {
|
|||
certReq := new(certificateRequestMsgTLS13)
|
||||
certReq.ocspStapling = true
|
||||
certReq.scts = true
|
||||
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(c.vers)
|
||||
certReq.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithmsCert()
|
||||
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(c.vers, c.vers)
|
||||
certReq.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithmsCert(c.vers, c.vers)
|
||||
if c.config.ClientCAs != nil {
|
||||
certReq.certificateAuthorities = c.config.ClientCAs.Subjects()
|
||||
}
|
||||
|
|
@ -1082,7 +1082,7 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error {
|
|||
// See RFC 8446, Section 4.4.3.
|
||||
// We don't use certReq.supportedSignatureAlgorithms because it would
|
||||
// require keeping the certificateRequestMsgTLS13 around in the hs.
|
||||
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms(c.vers)) ||
|
||||
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms(c.vers, c.vers)) ||
|
||||
!isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, signatureSchemesForPublicKey(c.vers, c.peerCertificates[0].PublicKey)) {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return errors.New("tls: client certificate used with invalid signature algorithm")
|
||||
|
|
|
|||
|
|
@ -483,12 +483,21 @@ func testHandshake(t *testing.T, clientConfig, serverConfig *Config) (serverStat
|
|||
c.Close()
|
||||
return
|
||||
}
|
||||
defer func() { errChan <- nil }()
|
||||
clientState = cli.ConnectionState()
|
||||
buf, err := io.ReadAll(cli)
|
||||
if err != nil {
|
||||
t.Errorf("failed to call cli.Read: %v", err)
|
||||
if serverConfig.ClientAuth != NoClientCert && clientState.Version == VersionTLS13 {
|
||||
// In TLS 1.3, client certificates are sent after the server's
|
||||
// handshake has completed, and the client only learns about it
|
||||
// reading the alert after the handshake.
|
||||
errChan <- fmt.Errorf("client (from Read): %v", err)
|
||||
c.Close()
|
||||
return
|
||||
} else {
|
||||
t.Errorf("failed to call cli.Read: %v", err)
|
||||
}
|
||||
}
|
||||
defer func() { errChan <- nil }()
|
||||
if got := string(buf); got != sentinel {
|
||||
t.Errorf("read %q from TLS connection, but expected %q", got, sentinel)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -294,6 +294,10 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
|
|||
if len(sig) < 2 {
|
||||
return errServerKeyExchange
|
||||
}
|
||||
switch ka.signatureAlgorithm {
|
||||
case MLDSA44, MLDSA65, MLDSA87:
|
||||
return errors.New("tls: server selected ML-DSA with TLS version < 1.3")
|
||||
}
|
||||
}
|
||||
sigLen := int(sig[0])<<8 | int(sig[1])
|
||||
if sigLen+2 != len(sig) {
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ func TestQUICPostHandshakeClientAuthentication(t *testing.T) {
|
|||
certReq := new(certificateRequestMsgTLS13)
|
||||
certReq.ocspStapling = true
|
||||
certReq.scts = true
|
||||
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS13)
|
||||
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS13, VersionTLS13)
|
||||
certReqBytes, err := certReq.marshal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/mldsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
|
|
@ -353,6 +354,14 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) {
|
|||
if !priv.Public().(ed25519.PublicKey).Equal(pub) {
|
||||
return fail(errors.New("tls: private key does not match public key"))
|
||||
}
|
||||
case *mldsa.PublicKey:
|
||||
priv, ok := cert.PrivateKey.(*mldsa.PrivateKey)
|
||||
if !ok {
|
||||
return fail(errors.New("tls: private key type does not match public key type"))
|
||||
}
|
||||
if !priv.PublicKey().Equal(pub) {
|
||||
return fail(errors.New("tls: private key does not match public key"))
|
||||
}
|
||||
default:
|
||||
return fail(errors.New("tls: unknown public key algorithm"))
|
||||
}
|
||||
|
|
@ -369,7 +378,7 @@ func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
|
|||
}
|
||||
if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
|
||||
switch key := key.(type) {
|
||||
case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey:
|
||||
case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey, *mldsa.PrivateKey:
|
||||
return key, nil
|
||||
default:
|
||||
return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping")
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import (
|
|||
"crypto/elliptic"
|
||||
"crypto/fips140"
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/cryptotest"
|
||||
"crypto/mldsa"
|
||||
"crypto/rand"
|
||||
"crypto/tls/internal/fips140tls"
|
||||
"crypto/x509"
|
||||
|
|
@ -40,16 +42,18 @@ import (
|
|||
var testTime = func() time.Time { return time.Unix(1476984729, 0) }
|
||||
|
||||
var testConfigServer = &Config{
|
||||
Time: testTime,
|
||||
Certificates: []Certificate{testECDSAP256Cert, testRSA2048Cert, testEd25519Cert, testSNICert},
|
||||
ClientCAs: testClientRootCertPool,
|
||||
Time: testTime,
|
||||
Certificates: []Certificate{testECDSAP256Cert, testRSA2048Cert, testEd25519Cert, testSNICert,
|
||||
testMLDSA44Cert, testMLDSA65Cert, testMLDSA87Cert},
|
||||
ClientCAs: testClientRootCertPool,
|
||||
}
|
||||
|
||||
var testConfigClient = &Config{
|
||||
Time: testTime,
|
||||
Certificates: []Certificate{testClientECDSAP256Cert, testClientRSA2048Cert, testClientEd25519Cert},
|
||||
RootCAs: testRootCertPool,
|
||||
ServerName: "test.golang.example",
|
||||
Time: testTime,
|
||||
Certificates: []Certificate{testClientECDSAP256Cert, testClientRSA2048Cert, testClientEd25519Cert,
|
||||
testClientMLDSA44Cert, testClientMLDSA65Cert, testClientMLDSA87Cert},
|
||||
RootCAs: testRootCertPool,
|
||||
ServerName: "test.golang.example",
|
||||
}
|
||||
|
||||
func TestX509KeyPair(t *testing.T) {
|
||||
|
|
@ -118,16 +122,25 @@ kohxS/xfFg/TEwRSSws+roJr4JFKpO2t3/be5OdqmQ==
|
|||
-----END EC TESTING KEY-----
|
||||
`)
|
||||
|
||||
var keyPairTests = []struct {
|
||||
type test struct {
|
||||
algo string
|
||||
cert string
|
||||
key string
|
||||
}{
|
||||
}
|
||||
var keyPairTests = []test{
|
||||
{"ECDSA", ecdsaCertPEM, ecdsaKeyPEM},
|
||||
{"RSA", rsaCertPEM, rsaKeyPEM},
|
||||
{"RSA-untyped", rsaCertPEM, keyPEM}, // golang.org/issue/4477
|
||||
}
|
||||
|
||||
if fips140.Version() != "v1.0.0" {
|
||||
keyPairTests = append(keyPairTests,
|
||||
test{"ML-DSA-44", testMLDSA44CertPEM, testingKey(testMLDSA44KeyPEM)},
|
||||
test{"ML-DSA-65", testMLDSA65CertPEM, testingKey(testMLDSA65KeyPEM)},
|
||||
test{"ML-DSA-87", testMLDSA87CertPEM, testingKey(testMLDSA87KeyPEM)},
|
||||
)
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
var pem []byte
|
||||
for _, test := range keyPairTests {
|
||||
|
|
@ -1571,6 +1584,25 @@ func TestClientHelloInfo_SupportsCertificate(t *testing.T) {
|
|||
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
|
||||
},
|
||||
}, ""}, // static RSA fallback
|
||||
|
||||
{testMLDSA44Cert, &ClientHelloInfo{
|
||||
SignatureSchemes: []SignatureScheme{MLDSA44},
|
||||
SupportedVersions: []uint16{VersionTLS13},
|
||||
}, ""},
|
||||
{testMLDSA65Cert, &ClientHelloInfo{
|
||||
SignatureSchemes: []SignatureScheme{MLDSA65},
|
||||
SupportedVersions: []uint16{VersionTLS13},
|
||||
}, ""},
|
||||
{testMLDSA87Cert, &ClientHelloInfo{
|
||||
SignatureSchemes: []SignatureScheme{MLDSA87},
|
||||
SupportedVersions: []uint16{VersionTLS13},
|
||||
}, ""},
|
||||
{testMLDSA44Cert, &ClientHelloInfo{
|
||||
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
|
||||
SupportedCurves: []CurveID{CurveP256},
|
||||
SupportedPoints: []uint8{pointFormatUncompressed},
|
||||
SupportedVersions: []uint16{VersionTLS12},
|
||||
}, "doesn't support ML-DSA"},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
err := tt.chi.SupportsCertificate(&tt.c)
|
||||
|
|
@ -2185,6 +2217,254 @@ func TestHandshakeMLKEM(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestSupportedSignatureAlgorithmsMLDSAGating asserts the spec-mandated
|
||||
// version-level gating of ML-DSA. Outside the FIPS 140-3 v1.0.0 module:
|
||||
// ML-DSA MUST NOT appear in the TLS 1.2 advertised list, MUST appear in
|
||||
// the TLS 1.3 advertised list. Under FIPS 140-3 v1.0.0 (which doesn't include
|
||||
// ML-DSA), ML-DSA MUST NOT be advertised in either extension.
|
||||
func TestSupportedSignatureAlgorithmsMLDSAGating(t *testing.T) {
|
||||
mldsaSchemes := []SignatureScheme{MLDSA44, MLDSA65, MLDSA87}
|
||||
|
||||
if fips140.Version() == "v1.0.0" {
|
||||
fullRange := supportedSignatureAlgorithms(VersionTLS10, VersionTLS13)
|
||||
certExt := supportedSignatureAlgorithmsCert(VersionTLS10, VersionTLS13)
|
||||
for _, s := range mldsaSchemes {
|
||||
if slices.Contains(fullRange, s) {
|
||||
t.Errorf("supportedSignatureAlgorithms contains %v under FIPS 140-3 v1.0.0", s)
|
||||
}
|
||||
if slices.Contains(certExt, s) {
|
||||
t.Errorf("supportedSignatureAlgorithmsCert contains %v under FIPS 140-3 v1.0.0", s)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
tls12Only := supportedSignatureAlgorithms(VersionTLS12, VersionTLS12)
|
||||
tls12OnlyCert := supportedSignatureAlgorithmsCert(VersionTLS12, VersionTLS12)
|
||||
for _, s := range mldsaSchemes {
|
||||
if slices.Contains(tls12Only, s) {
|
||||
t.Errorf("supportedSignatureAlgorithms(TLS12, TLS12) contains %v; ML-DSA must not be advertised in TLS 1.2", s)
|
||||
}
|
||||
if slices.Contains(tls12OnlyCert, s) {
|
||||
t.Errorf("supportedSignatureAlgorithmsCert(TLS12, TLS12) contains %v; ML-DSA must not be advertised in TLS 1.2", s)
|
||||
}
|
||||
}
|
||||
tls13Only := supportedSignatureAlgorithms(VersionTLS13, VersionTLS13)
|
||||
tls13OnlyCert := supportedSignatureAlgorithmsCert(VersionTLS13, VersionTLS13)
|
||||
for _, s := range mldsaSchemes {
|
||||
if !slices.Contains(tls13Only, s) {
|
||||
t.Errorf("supportedSignatureAlgorithms(TLS13, TLS13) is missing %v", s)
|
||||
}
|
||||
if !slices.Contains(tls13OnlyCert, s) {
|
||||
t.Errorf("supportedSignatureAlgorithmsCert(TLS13, TLS13) is missing %v", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshakeMLDSA(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
cert Certificate
|
||||
client Certificate
|
||||
}{
|
||||
{"MLDSA44", testMLDSA44Cert, testClientMLDSA44Cert},
|
||||
{"MLDSA65", testMLDSA65Cert, testClientMLDSA65Cert},
|
||||
{"MLDSA87", testMLDSA87Cert, testClientMLDSA87Cert},
|
||||
} {
|
||||
t.Run(tt.name+"/ServerAuth", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
serverConfig := testConfigServer.Clone()
|
||||
serverConfig.Certificates = []Certificate{tt.cert}
|
||||
clientConfig := testConfigClient.Clone()
|
||||
_, cs, err := testHandshake(t, clientConfig, serverConfig)
|
||||
if fips140.Version() == "v1.0.0" {
|
||||
if err == nil {
|
||||
t.Errorf("ML-DSA handshake unexpectedly succeeded with FIPS 140-3 module v1.0.0")
|
||||
}
|
||||
// Loaded certificate has cert bytes but no usable private key.
|
||||
if len(tt.cert.Certificate) == 0 {
|
||||
t.Errorf("certificate bytes missing")
|
||||
}
|
||||
if tt.cert.PrivateKey != nil {
|
||||
t.Errorf("PrivateKey = %T, want nil under v1.0.0", tt.cert.PrivateKey)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("handshake: %v", err)
|
||||
}
|
||||
if _, ok := cs.PeerCertificates[0].PublicKey.(*mldsa.PublicKey); !ok {
|
||||
t.Errorf("server peer cert public key = %T, want *mldsa.PublicKey",
|
||||
cs.PeerCertificates[0].PublicKey)
|
||||
}
|
||||
})
|
||||
t.Run(tt.name+"/ClientAuth", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
serverConfig := testConfigServer.Clone()
|
||||
serverConfig.Certificates = []Certificate{testECDSAP256Cert}
|
||||
serverConfig.ClientAuth = RequireAndVerifyClientCert
|
||||
clientConfig := testConfigClient.Clone()
|
||||
clientConfig.Certificates = []Certificate{tt.client}
|
||||
ss, _, err := testHandshake(t, clientConfig, serverConfig)
|
||||
if fips140.Version() == "v1.0.0" {
|
||||
if err == nil {
|
||||
t.Errorf("ML-DSA handshake unexpectedly succeeded with FIPS 140-3 module v1.0.0")
|
||||
}
|
||||
// Loaded certificate has cert bytes but no usable private key.
|
||||
if len(tt.client.Certificate) == 0 {
|
||||
t.Errorf("certificate bytes missing")
|
||||
}
|
||||
if tt.client.PrivateKey != nil {
|
||||
t.Errorf("PrivateKey = %T, want nil under v1.0.0", tt.client.PrivateKey)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("handshake: %v", err)
|
||||
}
|
||||
if _, ok := ss.PeerCertificates[0].PublicKey.(*mldsa.PublicKey); !ok {
|
||||
t.Errorf("client peer cert public key = %T, want *mldsa.PublicKey",
|
||||
ss.PeerCertificates[0].PublicKey)
|
||||
}
|
||||
})
|
||||
t.Run(tt.name+"/MutualAuth", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
serverConfig := testConfigServer.Clone()
|
||||
serverConfig.Certificates = []Certificate{tt.cert}
|
||||
serverConfig.ClientAuth = RequireAndVerifyClientCert
|
||||
clientConfig := testConfigClient.Clone()
|
||||
clientConfig.Certificates = []Certificate{tt.client}
|
||||
ss, cs, err := testHandshake(t, clientConfig, serverConfig)
|
||||
if fips140.Version() == "v1.0.0" {
|
||||
if err == nil {
|
||||
t.Errorf("ML-DSA handshake unexpectedly succeeded with FIPS 140-3 module v1.0.0")
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("handshake: %v", err)
|
||||
}
|
||||
if _, ok := cs.PeerCertificates[0].PublicKey.(*mldsa.PublicKey); !ok {
|
||||
t.Errorf("client-side peer cert public key = %T, want *mldsa.PublicKey",
|
||||
cs.PeerCertificates[0].PublicKey)
|
||||
}
|
||||
if _, ok := ss.PeerCertificates[0].PublicKey.(*mldsa.PublicKey); !ok {
|
||||
t.Errorf("server-side peer cert public key = %T, want *mldsa.PublicKey",
|
||||
ss.PeerCertificates[0].PublicKey)
|
||||
}
|
||||
})
|
||||
for _, v := range []uint16{VersionTLS10, VersionTLS12} {
|
||||
name := tt.name + "/RejectedVersion/" + VersionName(v)
|
||||
t.Run(name+"/Server", func(t *testing.T) {
|
||||
if v == VersionTLS10 {
|
||||
skipFIPS(t) // TLS 1.0 is not allowed in FIPS 140-3 mode.
|
||||
}
|
||||
cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.26.0")
|
||||
t.Parallel()
|
||||
serverConfig := testConfigServer.Clone()
|
||||
serverConfig.MinVersion = VersionTLS10
|
||||
serverConfig.Certificates = []Certificate{tt.cert}
|
||||
serverConfig.MaxVersion = v
|
||||
clientConfig := testConfigClient.Clone()
|
||||
clientConfig.MinVersion = VersionTLS10
|
||||
if _, _, err := testHandshake(t, clientConfig, serverConfig); err == nil {
|
||||
t.Fatal("expected handshake failure when ML-DSA is the only server cert and the negotiation is not TLS 1.3")
|
||||
} else if !strings.Contains(err.Error(), "ML-DSA") {
|
||||
t.Errorf("error message should mention ML-DSA, got %q", err)
|
||||
}
|
||||
|
||||
serverConfig.MaxVersion = 0
|
||||
clientConfig.MaxVersion = v
|
||||
if _, _, err := testHandshake(t, clientConfig, serverConfig); err == nil {
|
||||
t.Fatal("expected handshake failure when ML-DSA is the only server cert and the negotiation is not TLS 1.3")
|
||||
} else if !strings.Contains(err.Error(), "ML-DSA") {
|
||||
t.Errorf("error message should mention ML-DSA, got %q", err)
|
||||
}
|
||||
})
|
||||
t.Run(name+"/Client", func(t *testing.T) {
|
||||
cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.26.0")
|
||||
t.Parallel()
|
||||
serverConfig := testConfigServer.Clone()
|
||||
serverConfig.MinVersion = VersionTLS10
|
||||
serverConfig.ClientAuth = RequireAndVerifyClientCert
|
||||
clientConfig := testConfigClient.Clone()
|
||||
clientConfig.MinVersion = VersionTLS10
|
||||
clientConfig.Certificates = []Certificate{tt.client}
|
||||
clientConfig.MaxVersion = v
|
||||
if _, _, err := testHandshake(t, clientConfig, serverConfig); err == nil {
|
||||
t.Fatal("expected handshake failure when ML-DSA is the only client cert and the negotiation is not TLS 1.3")
|
||||
}
|
||||
// The error message on the client can't be helpful because we
|
||||
// don't know if the server requires a certificate until/unless
|
||||
// the server aborts later in the handshake, by which time we
|
||||
// lost track of which certificate we didn't offer and why.
|
||||
|
||||
clientConfig.MaxVersion = 0
|
||||
serverConfig.MaxVersion = v
|
||||
if _, _, err := testHandshake(t, clientConfig, serverConfig); err == nil {
|
||||
t.Fatal("expected handshake failure when ML-DSA is the only client cert and the negotiation is not TLS 1.3")
|
||||
}
|
||||
})
|
||||
}
|
||||
t.Run(tt.name+"/CorruptedSignature/Server", func(t *testing.T) {
|
||||
cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.26.0")
|
||||
t.Parallel()
|
||||
serverConfig := testConfigServer.Clone()
|
||||
serverConfig.Certificates = []Certificate{{
|
||||
Certificate: tt.cert.Certificate,
|
||||
PrivateKey: bitFlippingSigner{tt.cert.PrivateKey.(crypto.Signer)},
|
||||
}}
|
||||
clientConfig := testConfigClient.Clone()
|
||||
_, _, err := testHandshake(t, clientConfig, serverConfig)
|
||||
if err == nil {
|
||||
t.Fatal("handshake unexpectedly succeeded with corrupted ML-DSA signature")
|
||||
}
|
||||
// The client returns the verification error; the server returns
|
||||
// "remote error: tls: decrypt_error" reflecting the alert.
|
||||
if !strings.Contains(err.Error(), "decrypt") &&
|
||||
!strings.Contains(err.Error(), "ML-DSA verification failure") {
|
||||
t.Errorf("error = %q; want one mentioning decrypt_error or ML-DSA verification", err)
|
||||
}
|
||||
})
|
||||
t.Run(tt.name+"/CorruptedSignature/Client", func(t *testing.T) {
|
||||
cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.26.0")
|
||||
t.Parallel()
|
||||
serverConfig := testConfigServer.Clone()
|
||||
serverConfig.ClientAuth = RequireAndVerifyClientCert
|
||||
clientConfig := testConfigClient.Clone()
|
||||
clientConfig.Certificates = []Certificate{{
|
||||
Certificate: tt.client.Certificate,
|
||||
PrivateKey: bitFlippingSigner{tt.client.PrivateKey.(crypto.Signer)},
|
||||
}}
|
||||
_, _, err := testHandshake(t, clientConfig, serverConfig)
|
||||
if err == nil {
|
||||
t.Fatal("handshake unexpectedly succeeded with corrupted ML-DSA signature")
|
||||
}
|
||||
// The server returns the verification error; the client returns
|
||||
// "remote error: tls: decrypt_error" reflecting the alert.
|
||||
if !strings.Contains(err.Error(), "decrypt") &&
|
||||
!strings.Contains(err.Error(), "ML-DSA verification failure") {
|
||||
t.Errorf("error = %q; want one mentioning decrypt_error or ML-DSA verification", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// bitFlippingSigner wraps a crypto.Signer and flips the last bit of every
|
||||
// signature it produces, used to test that peers reject invalid signatures.
|
||||
type bitFlippingSigner struct{ crypto.Signer }
|
||||
|
||||
func (s bitFlippingSigner) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
|
||||
sig, err := s.Signer.Sign(rand, msg, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(sig) > 0 {
|
||||
sig[len(sig)-1] ^= 1
|
||||
}
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func TestX509KeyPairPopulateCertificate(t *testing.T) {
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue