DEV Community

Jason Shouldice
Jason Shouldice

Posted on • Originally published at vicistack.com

OpenSSL 3 Broke Your Asterisk TLS? Here's the 30-Second Fix

You ran apt upgrade. Maybe rebuilt a Docker image. Maybe migrated distros. Whatever it was, your Asterisk box was humming along with PJSIP endpoints connecting over TLS on port 5061. Then this showed up:

WARNING[12345]: pjproject: SSL SSL_ERROR_SSL (Handshake):
  err: <error:0A00017A:SSL routines::wrong curve>
Enter fullscreen mode Exit fullscreen mode

Phones stop registering. ATAs go offline. SIP trunks drop. Disabling TLS brings everything back, but that's giving up, not fixing anything.

The culprit: OpenSSL 3.x changed how it handles elliptic curve negotiation during TLS handshakes, and your SIP devices didn't get the memo.

What Actually Changed

OpenSSL 1.1.x was forgiving about curve mismatches. If a client offered curves that didn't perfectly match the server certificate's key type, it would usually find a workaround and proceed.

OpenSSL 3.0+ got strict about three things:

  1. Certificate key curves must match negotiated ECDH curves. P-384 cert + client only offering P-256 = "wrong curve" rejection.
  2. Default curve lists changed. OpenSSL 3.x defaults to X25519:P-256:P-384:P-521. Older SIP hardware often only supports P-256.
  3. ECDH auto-selection validates strictly. If the client doesn't advertise the server cert's curve, handshake fails immediately.

Why SIP Phones Get Hit Hardest

Grandstream, Yealink, Polycom, and Obihai devices ship firmware with limited curve support. A Grandstream HT801 might only advertise secp256r1 (P-256). It won't support X25519 or X448. If your Asterisk cert uses P-384, that device is locked out.

The cruel part: this breaks without any intentional change on your end. A base OS update or Docker image rebuild can silently swap OpenSSL 1.1.x for 3.x underneath Asterisk.

Diagnose It in 60 Seconds

# Confirm OpenSSL 3.x
openssl version

# Check your cert's curve
openssl x509 -in /etc/asterisk/keys/asterisk.pem -text -noout | grep -A 2 "Public Key"

# Simulate what your phone sees
openssl s_client -connect your-asterisk-ip:5061 -curves secp256r1 -tls1_2 2>&1 | head -30
Enter fullscreen mode Exit fullscreen mode

If you see ECDSA with secp384r1 or secp521r1 in the cert, and the s_client test fails -- that's your problem confirmed.

The Fix: Regenerate with P-256

P-256 (secp256r1) works with every SIP device on the market. This is almost always the right answer:

# Generate P-256 key
openssl ecparam -genkey -name prime256v1 -out /etc/asterisk/keys/asterisk.key

# Self-signed cert (10 years)
openssl req -new -x509 -key /etc/asterisk/keys/asterisk.key \
  -out /etc/asterisk/keys/asterisk.crt \
  -days 3650 -subj "/CN=asterisk.local/O=Asterisk PBX"

# Combine into PEM
cat /etc/asterisk/keys/asterisk.key /etc/asterisk/keys/asterisk.crt \
  > /etc/asterisk/keys/asterisk.pem

# Permissions
chown asterisk:asterisk /etc/asterisk/keys/*
chmod 600 /etc/asterisk/keys/asterisk.key

# Reload
asterisk -rx "module reload res_pjsip.so"
Enter fullscreen mode Exit fullscreen mode

Alternatively, use RSA 2048-bit to sidestep curve issues entirely:

openssl req -new -x509 -nodes -newkey rsa:2048 \
  -keyout /etc/asterisk/keys/asterisk.key \
  -out /etc/asterisk/keys/asterisk.crt \
  -days 3650 -subj "/CN=asterisk.local/O=Asterisk PBX"
Enter fullscreen mode Exit fullscreen mode

Alternative Fixes

Force curves in pjsip.conf (if you can't regenerate certs):

[tls-transport]
type = transport
protocol = tls
bind = 0.0.0.0:5061
cert_file = /etc/asterisk/keys/asterisk.crt
priv_key_file = /etc/asterisk/keys/asterisk.key
method = tlsv1_2
cipher = ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256
Enter fullscreen mode Exit fullscreen mode

System-wide OpenSSL config (/etc/ssl/openssl.cnf):

[system_default_sect]
Groups = P-256:P-384:X25519
Enter fullscreen mode Exit fullscreen mode

Docker users: Pin your base image. OpenSSL can silently upgrade between rebuilds. Mount certs and openssl.cnf from the host to control what's inside the container.

Device Compatibility Quick Reference

Device P-256 P-384 X25519
Grandstream HT80x Yes Sometimes No
Yealink T4x/T5x Yes Yes Firmware-dependent
Polycom VVX Yes Yes No
Obihai/Obi Yes No No
Linphone Yes Yes Yes

P-256 is the only curve guaranteed to work with everything.

Don't Chase the ca_list_file Red Herring

If you see ERROR: Failed to read CA list file, that's unrelated to the "wrong curve" error. For self-signed setups, you can safely omit ca_list_file and set verify_client = no. Don't waste time debugging CA chain issues when the real problem is curve negotiation.

Prevent It From Happening Again

  1. Pin your OpenSSL version in Docker images or package management
  2. Use P-256 for all new certificates
  3. Test TLS after every upgrade: echo | openssl s_client -connect localhost:5061 -tls1_2 2>&1 | grep -q "Verify return code" && echo "OK" || echo "BROKEN"
  4. Keep a backup of your last-known-good cert/key pair

The "wrong curve" error is OpenSSL 3.x being strict about something 1.1.x was lenient about. Don't panic, don't disable TLS, don't downgrade OpenSSL. Regenerate the cert with P-256 and move on. For more Asterisk configuration guides, check ViciStack's blog.

Originally published at https://vicistack.com/blog/asterisk-pjsip-tls-openssl3-guide/

Top comments (0)