Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
fail-fast: false
matrix:
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
go: ["1.24.x"]
go: ["1.27.x"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
Expand Down
15 changes: 15 additions & 0 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/mldsa"
"crypto/rsa"
"errors"
"fmt"
Expand Down Expand Up @@ -37,6 +38,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 {
Expand Down Expand Up @@ -105,6 +114,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)
}
Expand All @@ -119,6 +130,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)
}
Expand All @@ -140,6 +153,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)
}
Expand Down
7 changes: 7 additions & 0 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ const (
signatureECDSA
signatureEd25519
signatureEdDilithium3
signatureMLDSA
)

// directSigning is a standard Hash value that signals that no pre-hashing
Expand Down Expand Up @@ -414,6 +415,12 @@ const (
// EdDSA algorithms.
Ed25519 SignatureScheme = 0x0807

// ML-DSA signature algorithms (FIPS 204, RFC 9881). These codepoints are
// defined for TLS 1.3 only.
MLDSA44 SignatureScheme = 0x0904
MLDSA65 SignatureScheme = 0x0905
MLDSA87 SignatureScheme = 0x0906

// Legacy signature and hash algorithms for TLS 1.2.
PKCS1WithSHA1 SignatureScheme = 0x0201
ECDSAWithSHA1 SignatureScheme = 0x0203
Expand Down
46 changes: 42 additions & 4 deletions common_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/refraction-networking/utls

go 1.24
go 1.27

retract (
v1.4.1 // #218
Expand Down
6 changes: 6 additions & 0 deletions handshake_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/mldsa"
"crypto/mlkem"
"crypto/rsa"
"crypto/subtle"
Expand Down Expand Up @@ -1220,6 +1221,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)
Expand Down
2 changes: 1 addition & 1 deletion handshake_client_tls13.go
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error {
}

// See RFC 8446, Section 4.4.3.
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) {
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, clientSupportedSignatureAlgorithms(c.vers)) {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: certificate used with invalid signature algorithm")
}
Expand Down
8 changes: 7 additions & 1 deletion u_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ var (
HelloFirefox_120 = ClientHelloID{helloFirefox, "120", nil, nil}
HelloFirefox_148 = ClientHelloID{helloFirefox, "148", nil, nil}

HelloChrome_Auto = HelloChrome_133
HelloChrome_Auto = HelloChrome_150
HelloChrome_58 = ClientHelloID{helloChrome, "58", nil, nil}
HelloChrome_62 = ClientHelloID{helloChrome, "62", nil, nil}
HelloChrome_70 = ClientHelloID{helloChrome, "70", nil, nil}
Expand Down Expand Up @@ -645,6 +645,9 @@ var (
HelloChrome_131 = ClientHelloID{helloChrome, "131", nil, nil}
// Chrome w/ New ALPS codepoint
HelloChrome_133 = ClientHelloID{helloChrome, "133", nil, nil}
// Chrome w/ ML-DSA signature algorithms
HelloChrome_150 = ClientHelloID{helloChrome, "150", nil, nil}
HelloChrome_150_PSK = ClientHelloID{helloChrome, "150_PSK", nil, nil}

HelloIOS_Auto = HelloIOS_14
HelloIOS_11_1 = ClientHelloID{helloIOS, "111", nil, nil} // legacy "111" means 11.1
Expand All @@ -660,6 +663,9 @@ var (

HelloSafari_Auto = HelloSafari_26_3
HelloSafari_16_0 = ClientHelloID{helloSafari, "16.0", nil, nil}
HelloSafari_18_5 = ClientHelloID{helloSafari, "18.5", nil, nil}
// Safari 26.0 sends the same ClientHello as Safari 26.3.
HelloSafari_26_0 = ClientHelloID{helloSafari, "26.0", nil, nil}
HelloSafari_26_3 = ClientHelloID{helloSafari, "26.3", nil, nil}

Hello360_Auto = Hello360_7_5 // Hello360_11_0 seems to be incompatible with this library
Expand Down
Loading
Loading