From 0b0c05abb69d7e911d3fc42760d940b918d022dd Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Mon, 6 Apr 2026 15:52:30 -0500 Subject: [PATCH 1/6] Fix wolfSSH_ProcessBuffer to check type --- src/internal.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 74493adea..4411d6b85 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2403,7 +2403,10 @@ int wolfSSH_ProcessBuffer(WOLFSSH_CTX* ctx, if (der == NULL) return WS_MEMORY_E; - ret = wc_CertPemToDer(in, inSz, der, inSz, wcType); + if (type == BUFTYPE_PRIVKEY) + ret = wc_KeyPemToDer(in, inSz, der, inSz, NULL); + else + ret = wc_CertPemToDer(in, inSz, der, inSz, wcType); if (ret < 0) { WFREE(der, heap, dynamicType); return WS_BAD_FILE_E; From 37117df6844068ca4612c6ef7d7f31724d90ee09 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Mon, 6 Apr 2026 15:54:34 -0500 Subject: [PATCH 2/6] In SendKexDhReply, handle when WOLFSSH_CERTS is not defined --- src/internal.c | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/internal.c b/src/internal.c index 4411d6b85..887b82f9d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -12670,8 +12670,20 @@ int SendKexDhReply(WOLFSSH* ssh) * add it to the hash and then add K. */ if (ret == WS_SUCCESS) { sigBlockSz = (LENGTH_SZ * 2) + sigKeyBlock_ptr->pubKeyNameSz + sigSz; - payloadSz = MSG_ID_SZ + (LENGTH_SZ * 3) + - sigKeyBlock_ptr->sz + fSz + fPad + sigBlockSz; + #ifdef WOLFSSH_CERTS + if (sigKeyBlock_ptr->pubKeyFmtId == ID_X509V3_SSH_RSA + || sigKeyBlock_ptr->pubKeyFmtId == ID_X509V3_ECDSA_SHA2_NISTP256 + || sigKeyBlock_ptr->pubKeyFmtId == ID_X509V3_ECDSA_SHA2_NISTP384 + || sigKeyBlock_ptr->pubKeyFmtId == ID_X509V3_ECDSA_SHA2_NISTP521) { + payloadSz = MSG_ID_SZ + (LENGTH_SZ * 2) + + sigKeyBlock_ptr->sz + fSz + fPad + sigBlockSz; + } + else + #endif + { + payloadSz = MSG_ID_SZ + (LENGTH_SZ * 3) + + sigKeyBlock_ptr->sz + fSz + fPad + sigBlockSz; + } ret = PreparePacket(ssh, payloadSz); } @@ -12681,15 +12693,28 @@ int SendKexDhReply(WOLFSSH* ssh) output[idx++] = msgId; - /* Copy the key block size into the buffer */ - c32toa(sigKeyBlock_ptr->sz, output + idx); - idx += LENGTH_SZ; + #ifdef WOLFSSH_CERTS + if (sigKeyBlock_ptr->pubKeyFmtId == ID_X509V3_SSH_RSA + || sigKeyBlock_ptr->pubKeyFmtId == ID_X509V3_ECDSA_SHA2_NISTP256 + || sigKeyBlock_ptr->pubKeyFmtId == ID_X509V3_ECDSA_SHA2_NISTP384 + || sigKeyBlock_ptr->pubKeyFmtId == ID_X509V3_ECDSA_SHA2_NISTP521) { + /* BuildRFC6187Info writes the complete K_S including + * the outer length and key type name. Skip common header. */ + } + else + #endif + { + /* Copy the key block size into the buffer */ + c32toa(sigKeyBlock_ptr->sz, output + idx); + idx += LENGTH_SZ; - /* Copy the key name into the buffer */ - c32toa(sigKeyBlock_ptr->pubKeyFmtNameSz, output + idx); - idx += LENGTH_SZ; - WMEMCPY(output + idx, sigKeyBlock_ptr->pubKeyFmtName, sigKeyBlock_ptr->pubKeyFmtNameSz); - idx += sigKeyBlock_ptr->pubKeyFmtNameSz; + /* Copy the key name into the buffer */ + c32toa(sigKeyBlock_ptr->pubKeyFmtNameSz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, sigKeyBlock_ptr->pubKeyFmtName, + sigKeyBlock_ptr->pubKeyFmtNameSz); + idx += sigKeyBlock_ptr->pubKeyFmtNameSz; + } /* add host public key */ switch (sigKeyBlock_ptr->pubKeyFmtId) { From a89783e378b186f499eff43c58bffa59e9151e97 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Mon, 6 Apr 2026 15:57:38 -0500 Subject: [PATCH 3/6] Fix DoUserAuthRequestRsa() and DoUserAuthRequestRsaCert() to accept ssh-rsa, rsa-sha2-256, and rsa-sha2-512 --- src/internal.c | 59 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/src/internal.c b/src/internal.c index 887b82f9d..f75f435b3 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7043,11 +7043,33 @@ static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, } if (ret == WS_SUCCESS) { - if (publicKeyTypeSz != pk->publicKeyTypeSz - || publicKeyType == NULL - || WMEMCMP(publicKeyType, pk->publicKeyType, - publicKeyTypeSz) != 0) { - + int sigTypeOk = 0; + if (publicKeyType != NULL) { + if (publicKeyTypeSz == pk->publicKeyTypeSz + && WMEMCMP(publicKeyType, pk->publicKeyType, + publicKeyTypeSz) == 0) { + sigTypeOk = 1; + } + #ifdef WOLFSSH_CERTS + else if (pk->publicKeyTypeSz == 14 + && WMEMCMP(pk->publicKeyType, + "x509v3-ssh-rsa", 14) == 0) { + /* RFC 6187 Section 5: the signature uses the underlying + * RSA algorithm, not the X.509 key type name. */ + if ((publicKeyTypeSz == 7 + && WMEMCMP(publicKeyType, "ssh-rsa", 7) == 0) + || (publicKeyTypeSz == 12 + && WMEMCMP(publicKeyType, + "rsa-sha2-256", 12) == 0) + || (publicKeyTypeSz == 12 + && WMEMCMP(publicKeyType, + "rsa-sha2-512", 12) == 0)) { + sigTypeOk = 1; + } + } + #endif + } + if (!sigTypeOk) { WLOG(WS_LOG_DEBUG, "Signature's type does not match public key type"); ret = WS_INVALID_ALGO_ID; @@ -7182,10 +7204,29 @@ static int DoUserAuthRequestRsaCert(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, } if (ret == WS_SUCCESS) { - if (publicKeyTypeSz != pk->publicKeyTypeSz - || WMEMCMP(publicKeyType, pk->publicKeyType, - publicKeyTypeSz) != 0) { - + int sigTypeOk = 0; + if (publicKeyTypeSz == pk->publicKeyTypeSz + && WMEMCMP(publicKeyType, pk->publicKeyType, + publicKeyTypeSz) == 0) { + sigTypeOk = 1; + } + #ifdef WOLFSSH_CERTS + else if (pk->publicKeyFmtId == ID_X509V3_SSH_RSA) { + /* RFC 6187 Section 5: the signature uses the underlying + * RSA algorithm, not the X.509 key type name. */ + if ((publicKeyTypeSz == 7 + && WMEMCMP(publicKeyType, "ssh-rsa", 7) == 0) + || (publicKeyTypeSz == 12 + && WMEMCMP(publicKeyType, + "rsa-sha2-256", 12) == 0) + || (publicKeyTypeSz == 12 + && WMEMCMP(publicKeyType, + "rsa-sha2-512", 12) == 0)) { + sigTypeOk = 1; + } + } + #endif + if (!sigTypeOk) { WLOG(WS_LOG_DEBUG, "Signature's type does not match public key type"); ret = WS_INVALID_ALGO_ID; From 0bb1d1b5b74ff0aed16bcc835cac18ad713974a2 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Mon, 6 Apr 2026 16:13:41 -0500 Subject: [PATCH 4/6] Add test case test_wolfSSH_CTX_UsePrivateKey_buffer_pem --- tests/api.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/api.c b/tests/api.c index bc65e2beb..d4d6ec221 100644 --- a/tests/api.c +++ b/tests/api.c @@ -593,6 +593,49 @@ static void test_wolfSSH_CTX_UseCert_buffer(void) } +static void test_wolfSSH_CTX_UsePrivateKey_buffer_pem(void) +{ +#if defined(WOLFSSH_CERTS) && !defined(WOLFSSH_NO_SERVER) + WOLFSSH_CTX* ctx = NULL; + byte* key = NULL; + word32 keySz = 0; + + ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL); + AssertNotNull(ctx); + +#ifndef WOLFSSH_NO_RSA + AssertIntEQ(0, load_file("./keys/server-key-rsa.pem", &key, &keySz)); + AssertNotNull(key); + AssertIntNE(0, keySz); + + /* PEM private key should load successfully */ + AssertIntEQ(WS_SUCCESS, + wolfSSH_CTX_UsePrivateKey_buffer(ctx, key, keySz, + WOLFSSH_FORMAT_PEM)); + + free(key); + key = NULL; +#endif /* WOLFSSH_NO_RSA */ + +#ifndef WOLFSSH_NO_ECDSA + AssertIntEQ(0, load_file("./keys/server-key-ecc.pem", &key, &keySz)); + AssertNotNull(key); + AssertIntNE(0, keySz); + + /* PEM ECC private key should load successfully */ + AssertIntEQ(WS_SUCCESS, + wolfSSH_CTX_UsePrivateKey_buffer(ctx, key, keySz, + WOLFSSH_FORMAT_PEM)); + + free(key); + key = NULL; +#endif /* WOLFSSH_NO_ECDSA */ + + wolfSSH_CTX_free(ctx); +#endif /* WOLFSSH_CERTS && !WOLFSSH_NO_SERVER */ +} + + static void test_wolfSSH_CertMan(void) { #ifdef WOLFSSH_CERTMAN @@ -1990,6 +2033,7 @@ int wolfSSH_ApiTest(int argc, char** argv) test_wolfSSH_ConvertConsole(); test_wolfSSH_CTX_UsePrivateKey_buffer(); test_wolfSSH_CTX_UseCert_buffer(); + test_wolfSSH_CTX_UsePrivateKey_buffer_pem(); test_wolfSSH_CertMan(); test_wolfSSH_ReadKey(); test_wolfSSH_QueryAlgoList(); From 9dfa93f4b9bd3e1d3b1bf38991a5db53a9eee1e5 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Mon, 6 Apr 2026 16:23:25 -0500 Subject: [PATCH 5/6] Fix from review --- src/internal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index f75f435b3..e1ab4fd0b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7211,7 +7211,9 @@ static int DoUserAuthRequestRsaCert(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, sigTypeOk = 1; } #ifdef WOLFSSH_CERTS - else if (pk->publicKeyFmtId == ID_X509V3_SSH_RSA) { + else if (pk->publicKeyTypeSz == 14 + && WMEMCMP(pk->publicKeyType, + "x509v3-ssh-rsa", 14) == 0) { /* RFC 6187 Section 5: the signature uses the underlying * RSA algorithm, not the X.509 key type name. */ if ((publicKeyTypeSz == 7 From 31a06d356d578fc3a8a1b0b4edb15abceedbba28 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Mon, 6 Apr 2026 16:26:26 -0500 Subject: [PATCH 6/6] Fix from review --- src/internal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/internal.c b/src/internal.c index e1ab4fd0b..eec2b1f06 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7205,13 +7205,15 @@ static int DoUserAuthRequestRsaCert(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, if (ret == WS_SUCCESS) { int sigTypeOk = 0; - if (publicKeyTypeSz == pk->publicKeyTypeSz + if (publicKeyType != NULL + && publicKeyTypeSz == pk->publicKeyTypeSz && WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) == 0) { sigTypeOk = 1; } #ifdef WOLFSSH_CERTS - else if (pk->publicKeyTypeSz == 14 + else if (publicKeyType != NULL + && pk->publicKeyTypeSz == 14 && WMEMCMP(pk->publicKeyType, "x509v3-ssh-rsa", 14) == 0) { /* RFC 6187 Section 5: the signature uses the underlying