Skip to content
Open
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
67 changes: 54 additions & 13 deletions apps/wolfsshd/wolfsshd.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,8 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
byte** banner)
{
int ret = WS_SUCCESS;
DerBuffer* der = NULL;
byte* privBuf;
word32 privBufSz;
byte* privBuf = NULL;
word32 privBufSz = 0;
void* heap = NULL;

if (ctx == NULL) {
Expand Down Expand Up @@ -412,28 +411,70 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
}

if (ret == WS_SUCCESS) {
if (wc_PemToDer(data, dataSz, PRIVATEKEY_TYPE, &der, NULL,
NULL, NULL) != 0) {
wolfSSH_Log(WS_LOG_DEBUG, "[SSHD] Failed to convert host "
"private key from PEM. Assuming key in DER "
"format.");
/* Host keys may be PEM or DER. Detect by content: a DER key is
* an ASN.1 SEQUENCE (leading 0x30); anything else is treated as
* PEM text and decoded with wc_KeyPemToDer(), which handles
* PKCS#1, SEC1 and PKCS#8 "PRIVATE KEY" bodies.
*
* The previous code used wc_PemToDer(..., PRIVATEKEY_TYPE, ...),
* which only recognizes the classic "RSA/EC PRIVATE KEY" PEM
* headers. On a PKCS#8 body (how ML-DSA host keys are emitted)
* it returns *success* but yields a malformed body (leading
* 0x04, not a 0x30 SEQUENCE), which
* wolfSSH_CTX_UsePrivateKey_buffer() then rejects with
* WS_BAD_FILETYPE_E, so ML-DSA PEM host keys could not load. */
byte* keyDer = NULL;

if (dataSz == 0) {
/* An empty (0-byte) file passes the NULL check above but
* carries no key material. Handle it explicitly as a file
* error instead of falling into the PEM path, where
* WMALLOC(0) is implementation-defined (may return NULL and
* be misreported as WS_MEMORY_E). */
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Host key file is empty.");
ret = WS_BAD_FILE_E;
}
else if (data[0] == 0x30) {
privBuf = data;
privBufSz = dataSz;
}
else {
privBuf = der->buffer;
privBufSz = der->length;
keyDer = (byte*)WMALLOC(dataSz, heap, DYNTYPE_SSHD);
if (keyDer == NULL) {
ret = WS_MEMORY_E;
}
else {
int keyDerSz = wc_KeyPemToDer(data, dataSz, keyDer,
(int)dataSz, NULL);
if (keyDerSz <= 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failed to convert "
"host private key from PEM.");
ret = WS_BAD_FILE_E;
}
else {
privBuf = keyDer;
privBufSz = (word32)keyDerSz;
}
}
}

if (wolfSSH_CTX_UsePrivateKey_buffer(*ctx, privBuf, privBufSz,
WOLFSSH_FORMAT_ASN1) < 0) {
if (ret == WS_SUCCESS
&& wolfSSH_CTX_UsePrivateKey_buffer(*ctx, privBuf,
privBufSz, WOLFSSH_FORMAT_ASN1) < 0) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Failed to use host private key.");
ret = WS_BAD_ARGUMENT;
}

if (keyDer != NULL) {
WS_FORCEZERO(keyDer, dataSz);
WFREE(keyDer, heap, DYNTYPE_SSHD);
}
/* data held the raw private key — the DER bytes, or the PEM
* text decoded into keyDer above. Zeroize before freeing so key
* material does not linger in the heap after use. */
WS_FORCEZERO(data, dataSz);
freeBufferFromFile(data, heap);
wc_FreeDer(&der);
}
Comment thread
ejohnstown marked this conversation as resolved.
}
}
Expand Down
Loading