Skip to content

SSH panic when using EC key #316

@stanhu

Description

@stanhu

When I try a simple SSH client with go1.24.5-1-openssl-fips, I get:

Testing SSH connection to gitlab.com:22 as user stanhu...
panic: curve25519: internal error: scalarBaseMult was not 32 bytes

goroutine 10 [running]:
golang.org/x/crypto/curve25519.ScalarBaseMult(0xc00001a460, 0x6a34e0?)
        /root/go/pkg/mod/golang.org/x/crypto@v0.41.0/curve25519/curve25519.go:39 +0x13b
golang.org/x/crypto/ssh.(*curve25519KeyPair).generate(0xc00001a440, {0x6a5720?, 0x6a34e0?})
        /root/go/pkg/mod/golang.org/x/crypto@v0.41.0/ssh/kex.go:457 +0x65
golang.org/x/crypto/ssh.(*curve25519sha256).Client(0xa048b0?, {0x7f6c0a7f0a00, 0xc000112120}, {0x6a5720, 0x6a34e0}, 0xc0000704e0)
        /root/go/pkg/mod/golang.org/x/crypto@v0.41.0/ssh/kex.go:468 +0x6e
golang.org/x/crypto/ssh.(*handshakeTransport).client(0xc000104680, {0x6a5a40?, 0xa4d0e0?}, 0xc0000704e0?)
        /root/go/pkg/mod/golang.org/x/crypto@v0.41.0/ssh/handshake.go:826 +0x66
golang.org/x/crypto/ssh.(*handshakeTransport).enterKeyExchange(0xc000104680, {0xc0000d8300, 0x2e7, 0x2e7})
        /root/go/pkg/mod/golang.org/x/crypto@v0.41.0/ssh/handshake.go:716 +0x49a
golang.org/x/crypto/ssh.(*handshakeTransport).kexLoop(0xc000104680)
        /root/go/pkg/mod/golang.org/x/crypto@v0.41.0/ssh/handshake.go:345 +0x98
created by golang.org/x/crypto/ssh.newClientTransport in goroutine 1
        /root/go/pkg/mod/golang.org/x/crypto@v0.41.0/ssh/handshake.go:170 +0x256

Is this similar to 896a14d where EC keys are not disabled in FIPS mode when using SSH?

Reproduction client:

package main

import (
	"fmt"
	"log"
	"os"
	"os/user"
	"time"

	"golang.org/x/crypto/ssh"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run ssh-test.go <host:port> [username]")
		fmt.Println("Example: go run ssh-test.go example.com:22")
		fmt.Println("Example: go run ssh-test.go 192.168.1.100:2222 myuser")
		os.Exit(1)
	}

	address := os.Args[1]
	username := "root" // default

	if len(os.Args) > 2 {
		username = os.Args[2]
	} else {
		// Try to get current user
		if currentUser, err := user.Current(); err == nil {
			username = currentUser.Username
		}
	}

	fmt.Printf("Testing SSH connection to %s as user %s...\n", address, username)

	config := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{
			ssh.Password(""), // Try empty password first
			ssh.PasswordCallback(func() (string, error) {
				fmt.Print("Enter password: ")
				var password string
				fmt.Scanln(&password)
				return password, nil
			}),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // Accept any host key
		Timeout:         10 * time.Second,
	}

	client, err := ssh.Dial("tcp", address, config)
	if err != nil {
		log.Fatalf("❌ Connection failed: %v", err)
	}
	defer client.Close()

	// Test by running a simple command
	session, err := client.NewSession()
	if err != nil {
		log.Fatalf("❌ Session creation failed: %v", err)
	}
	defer session.Close()

	output, err := session.Output("echo 'SSH connection test successful'")
	if err != nil {
		log.Fatalf("❌ Command execution failed: %v", err)
	}

	fmt.Printf("✅ Connection successful!\n")
	fmt.Printf("Server response: %s", output)
	fmt.Printf("Client version: %s\n", client.ClientVersion())
	fmt.Printf("Server version: %s\n", client.ServerVersion())
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions