Skip to content

wolfsshd: load PKCS#8 PEM host keys (e.g. ML-DSA)#1118

Open
shaunchokshi wants to merge 1 commit into
wolfSSL:masterfrom
CK-Consulting:fix/wolfsshd-pkcs8-pem-hostkey
Open

wolfsshd: load PKCS#8 PEM host keys (e.g. ML-DSA)#1118
shaunchokshi wants to merge 1 commit into
wolfSSL:masterfrom
CK-Consulting:fix/wolfsshd-pkcs8-pem-hostkey

Conversation

@shaunchokshi

Copy link
Copy Markdown

wolfsshd could not load a host key stored as a PKCS#8 -----BEGIN PRIVATE KEY----- PEM file (the form emitted for ML-DSA keys, and by openssl genpkey).

SetupCTX() pre-converted the file with wc_PemToDer(..., PRIVATEKEY_TYPE, ...), which only recognizes the classic RSA/EC PRIVATE KEY headers. On a PKCS#8 body that call returns success but produces a malformed DER (leading 0x04 rather than a 0x30 SEQUENCE); the bytes were then passed to wolfSSH_CTX_UsePrivateKey_buffer() as WOLFSSH_FORMAT_ASN1, which rejected them with WS_BAD_FILETYPE_E (-1016).

Detect PEM vs DER by content and decode PEM with wc_KeyPemToDer(), which handles PKCS#1, SEC1 and PKCS#8 private-key bodies. DER keys are unchanged.

Testing

Built against wolfSSL master; same wolfsshd binary run against three host keys with the patch toggled on and off, reading the wolfSSH_CTX_UsePrivateKey_buffer() return from -D -d output:

Host key Before After
ML-DSA-65 PEM (PKCS#8) ret = -1016, "Failed to use host private key" ret = 0
ML-DSA-65 DER ret = 0 ret = 0 (no regression)
ECDSA SEC1 PEM ret = 0 ret = 0 (no regression)

The ML-DSA PEM key was generated with wolfssl genkey ml-dsa -level 3 -output priv -outform PEM.

No ChangeLog.md entry is included — the top section is the released v1.5.0; happy to add one wherever you'd like it. Suggested wording: "Fixed loading PKCS#8 PEM host keys in wolfSSHd (e.g. ML-DSA)."

@wolfSSL-Bot

Copy link
Copy Markdown

Can one of the admins verify this patch?

@dgarske

dgarske commented Jul 22, 2026

Copy link
Copy Markdown
Member

See ZD 22185

@ejohnstown
ejohnstown self-requested a review July 22, 2026 22:53
Comment thread apps/wolfsshd/wolfsshd.c Outdated
Comment thread apps/wolfsshd/wolfsshd.c Outdated
@shaunchokshi
shaunchokshi requested a review from ejohnstown July 23, 2026 04:11

@ejohnstown ejohnstown left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't accept that commit from Claude. Can you squash it into the other commit and force-push it again, please?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates wolfsshd host-key loading so it can successfully load PKCS#8 PEM private keys (-----BEGIN PRIVATE KEY-----), including the format produced for ML-DSA keys, while preserving existing DER host-key behavior.

Changes:

  • Detect host-key input as DER vs PEM by content and decode PEM using wc_KeyPemToDer() (supports PKCS#1/SEC1/PKCS#8).
  • Continue passing DER bytes unchanged to wolfSSH_CTX_UsePrivateKey_buffer() as ASN.1.
  • Add cleanup for the temporary DER buffer used during PEM conversion.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/wolfsshd/wolfsshd.c Outdated
Comment thread apps/wolfsshd/wolfsshd.c

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #1118

Scan targets checked: wolfssh-bugs, wolfssh-src

No new issues found in the changed files. ✅

@shaunchokshi
shaunchokshi force-pushed the fix/wolfsshd-pkcs8-pem-hostkey branch from 6d6373e to af83564 Compare July 23, 2026 17:46
wolfsshd could not load a host key stored as a PKCS#8 "-----BEGIN PRIVATE KEY-----"
PEM file (the form emitted for ML-DSA keys, and by `openssl genpkey`).

SetupCTX() pre-converted the file with wc_PemToDer(..., PRIVATEKEY_TYPE, ...),
which only recognizes the classic "RSA/EC PRIVATE KEY" headers. On a PKCS#8 body
that call returns success but produces a malformed DER (leading 0x04 rather than a
0x30 SEQUENCE); the bytes were then passed to wolfSSH_CTX_UsePrivateKey_buffer()
as WOLFSSH_FORMAT_ASN1, which rejected them with WS_BAD_FILETYPE_E.

Detect PEM vs DER by content and decode PEM with wc_KeyPemToDer(), which handles
PKCS#1, SEC1 and PKCS#8 private-key bodies. DER keys are unchanged.

Tested (master + wolfSSL master): an ML-DSA-65 PEM host key now loads
(wolfSSH_CTX_UsePrivateKey_buffer ret = 0, was WS_BAD_FILETYPE_E); ML-DSA-65 DER
and ECDSA SEC1 PEM host keys continue to load (no regression).

Also harden the host-key load path per review: reject an empty (0-byte)
key file explicitly instead of taking the PEM branch into WMALLOC(0), and
zeroize the raw file buffer (not just the decoded DER) before freeing so
private-key material does not linger in the heap.
@shaunchokshi
shaunchokshi force-pushed the fix/wolfsshd-pkcs8-pem-hostkey branch from af83564 to ac50255 Compare July 23, 2026 18:32
@shaunchokshi

Copy link
Copy Markdown
Author

Squashed to a single commit, and addressed both Copilot findings in it: empty (0-byte) host-key files now return a file error before the PEM path (no WMALLOC(0)), and the raw key buffer is zeroized before free alongside the decoded DER. Thanks for the patience!

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #1118

Scan targets checked: wolfssh-bugs, wolfssh-src

No new issues found in the changed files. ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants