From 39f30e25a407f50d474bdf2e94513eb7afb1c27c Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 4 Sep 2020 15:28:25 -0700 Subject: [PATCH] Optional RSA 1. If RSA is disabled in the wolfCrypt build, the RSA related code in wolfSSH shall be disabled. 2. Examples will force themselves to use ECC if RSA is disabled. --- examples/client/client.c | 4 +++ examples/echoserver/echoserver.c | 6 ++++ examples/server/server.c | 5 +++ examples/sftpclient/sftpclient.c | 5 +++ src/agent.c | 6 ++++ src/internal.c | 62 +++++++++++++++++++++++++++----- src/keygen.c | 9 +++++ src/ssh.c | 9 +++-- tests/api.c | 7 +++- 9 files changed, 102 insertions(+), 11 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index c1e5752..e63baa9 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -869,6 +869,10 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) if (username == NULL) err_sys("client requires a username parameter."); +#ifdef NO_RSA + userEcc = 1; +#endif + #ifdef SINGLE_THREADED if (keepOpen) err_sys("Threading needed for terminal session\n"); diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index c57a17c..fb4d598 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -1602,6 +1602,12 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) } #endif +#ifdef NO_RSA + /* If wolfCrypt isn't built with RSA, force ECC on. */ + userEcc = 1; + peerEcc = 1; +#endif + if (wolfSSH_Init() != WS_SUCCESS) { fprintf(stderr, "Couldn't initialize wolfSSH.\n"); exit(EXIT_FAILURE); diff --git a/examples/server/server.c b/examples/server/server.c index e0bf1bd..20ee2b6 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -660,6 +660,11 @@ THREAD_RETURN WOLFSSH_THREAD server_test(void* args) } myoptind = 0; /* reset for test cases */ +#ifdef NO_RSA + /* If wolfCrypt isn't built with RSA, force ECC on. */ + useEcc = 1; +#endif + if (wolfSSH_Init() != WS_SUCCESS) { fprintf(stderr, "Couldn't initialize wolfSSH.\n"); exit(EXIT_FAILURE); diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index 9c90075..c980f04 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -1329,6 +1329,11 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) if (username == NULL) err_sys("client requires a username parameter."); +#ifdef NO_RSA + userEcc = 1; + /* peerEcc = 1; */ +#endif + if (autopilot != AUTOPILOT_OFF) { if (apLocal == NULL || apRemote == NULL) { err_sys("Options -G and -g require both -l and -r."); diff --git a/src/agent.c b/src/agent.c index 28e4d80..59a6774 100644 --- a/src/agent.c +++ b/src/agent.c @@ -379,6 +379,7 @@ static int PostUnlock(WOLFSSH_AGENT_CTX* agent, } +#ifndef NO_RSA static int PostAddRsaId(WOLFSSH_AGENT_CTX* agent, byte keyType, byte* key, word32 keySz, word32 nSz, word32 eSz, word32 dSz, @@ -457,6 +458,7 @@ static int PostAddRsaId(WOLFSSH_AGENT_CTX* agent, WLOG_LEAVE(ret); return ret; } +#endif static int PostAddEcdsaId(WOLFSSH_AGENT_CTX* agent, @@ -667,6 +669,7 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent, int sigSz = sizeof(sig); if (cur->keyType == ID_SSH_RSA) { +#ifndef NO_RSA WOLFSSH_AGENT_KEY_RSA* key; RsaKey rsa; byte encSig[MAX_ENCODED_SIG_SZ]; @@ -708,6 +711,7 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent, wc_FreeRsaKey(&rsa); if (ret != 0) ret = WS_RSA_E; +#endif } else if (cur->keyType == ID_ECDSA_SHA2_NISTP256) { WOLFSSH_AGENT_KEY_ECDSA* key; @@ -942,6 +946,7 @@ static int DoAddIdentity(WOLFSSH_AGENT_CTX* agent, begin += sz; if (keyType == ID_SSH_RSA) { +#ifndef NO_RSA byte* key; byte* scratch; word32 keySz, nSz, eSz, dSz, iqmpSz, pSz, qSz, commentSz; @@ -983,6 +988,7 @@ static int DoAddIdentity(WOLFSSH_AGENT_CTX* agent, ret = PostAddRsaId(agent, keyType, key, keySz, nSz, eSz, dSz, iqmpSz, pSz, qSz, commentSz); } +#endif } else if (keyType == ID_ECDSA_SHA2_NISTP256 || keyType == ID_ECDSA_SHA2_NISTP384 || diff --git a/src/internal.c b/src/internal.c index 6dac8a7..8f11a9d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -679,12 +679,15 @@ int wolfSSH_ProcessBuffer(WOLFSSH_CTX* ctx, if (type == BUFTYPE_PRIVKEY && format != WOLFSSH_FORMAT_RAW) { /* Check RSA key */ union { +#ifndef NO_RSA RsaKey rsa; +#endif ecc_key ecc; } key; word32 scratch = 0; int ret; +#ifndef NO_RSA if (wc_InitRsaKey(&key.rsa, NULL) < 0) return WS_RSA_E; @@ -692,6 +695,7 @@ int wolfSSH_ProcessBuffer(WOLFSSH_CTX* ctx, wc_FreeRsaKey(&key.rsa); if (ret < 0) { +#endif /* Couldn't decode as RSA key. Try decoding as ECC key. */ scratch = 0; if (wc_ecc_init_ex(&key.ecc, ctx->heap, INVALID_DEVID) != 0) @@ -714,7 +718,9 @@ int wolfSSH_ProcessBuffer(WOLFSSH_CTX* ctx, if (ret != 0) return WS_BAD_FILE_E; +#ifndef NO_RSA } +#endif } return WS_SUCCESS; @@ -2534,9 +2540,11 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) byte useRsa; word32 keySz; union { +#ifndef NO_RSA struct { RsaKey key; } rsa; +#endif struct { ecc_key key; } ecc; @@ -2733,6 +2741,7 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) sigKeyBlock.useRsa = ssh->handshake->pubKeyId == ID_SSH_RSA; if (sigKeyBlock.useRsa) { +#ifndef NO_RSA byte* e; word32 eSz; byte* n; @@ -2767,6 +2776,9 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) sigKeyBlock.keySz = sizeof(sigKeyBlock.sk.rsa.key); else ret = WS_RSA_E; +#else + (void)tmpIdx; +#endif } else { byte* q; @@ -2901,6 +2913,7 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) } if (ret == WS_SUCCESS) { if (sigKeyBlock.useRsa) { +#ifndef NO_RSA sig = sig + begin; /* In the fuzz, sigSz ends up 1 and it has issues. */ sigSz = scratch; @@ -2929,6 +2942,7 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) ret = WS_RSA_E; } } +#endif } else { byte* r; @@ -2966,8 +2980,11 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) } } - if (sigKeyBlock.useRsa) + if (sigKeyBlock.useRsa) { +#ifndef NO_RSA wc_FreeRsaKey(&sigKeyBlock.sk.rsa.key); +#endif + } else wc_ecc_free(&sigKeyBlock.sk.ecc.key); } @@ -3558,7 +3575,7 @@ static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData, return ret; } - +#ifndef NO_RSA /* Utility for DoUserAuthRequestPublicKey() */ /* returns negative for error, positive is size of digest. */ static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, @@ -3678,6 +3695,7 @@ static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestRsa(), ret = %d", ret); return ret; } +#endif /* Utility for DoUserAuthRequestPublicKey() */ @@ -3962,9 +3980,12 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData, } if (ret == WS_SUCCESS) { - if (pkTypeId == ID_SSH_RSA) + if (pkTypeId == ID_SSH_RSA) { +#ifndef NO_RSA ret = DoUserAuthRequestRsa(ssh, pk, hashId, digest, digestSz); +#endif + } else if (pkTypeId == ID_ECDSA_SHA2_NISTP256 || pkTypeId == ID_ECDSA_SHA2_NISTP384 || pkTypeId == ID_ECDSA_SHA2_NISTP521) @@ -6056,6 +6077,7 @@ int SendKexDhReply(WOLFSSH* ssh) const char *name; word32 nameSz; union { +#ifndef NO_RSA struct { RsaKey key; byte e[257]; @@ -6065,6 +6087,7 @@ int SendKexDhReply(WOLFSSH* ssh) word32 nSz; byte nPad; } rsa; +#endif struct { ecc_key key; word32 keyBlobSz; @@ -6134,6 +6157,7 @@ int SendKexDhReply(WOLFSSH* ssh) * either be RSA or ECDSA public key blob. */ if (ret == WS_SUCCESS) { if (sigKeyBlock.useRsa) { +#ifndef NO_RSA /* Decode the user-configured RSA private key. */ sigKeyBlock.sk.rsa.eSz = sizeof(sigKeyBlock.sk.rsa.e); sigKeyBlock.sk.rsa.nSz = sizeof(sigKeyBlock.sk.rsa.n); @@ -6223,6 +6247,7 @@ int SendKexDhReply(WOLFSSH* ssh) enmhashId, sigKeyBlock.sk.rsa.n, sigKeyBlock.sk.rsa.nSz); +#endif } else { sigKeyBlock.sk.ecc.primeName = @@ -6511,6 +6536,7 @@ int SendKexDhReply(WOLFSSH* ssh) if (ret == WS_SUCCESS) { if (sigKeyBlock.useRsa) { +#ifndef NO_RSA byte encSig[MAX_ENCODED_SIG_SZ]; word32 encSigSz; @@ -6530,6 +6556,7 @@ int SendKexDhReply(WOLFSSH* ssh) ret = WS_RSA_E; } } +#endif } else { WLOG(WS_LOG_INFO, "Signing hash with ECDSA."); @@ -6573,10 +6600,14 @@ int SendKexDhReply(WOLFSSH* ssh) } } - if (sigKeyBlock.useRsa) + if (sigKeyBlock.useRsa) { +#ifndef NO_RSA wc_FreeRsaKey(&sigKeyBlock.sk.rsa.key); - else +#endif + } + else { wc_ecc_free(&sigKeyBlock.sk.ecc.key); + } sigBlockSz = (LENGTH_SZ * 2) + sigKeyBlock.nameSz + sigSz; @@ -6605,6 +6636,7 @@ int SendKexDhReply(WOLFSSH* ssh) WMEMCPY(output + idx, sigKeyBlock.name, sigKeyBlock.nameSz); idx += sigKeyBlock.nameSz; if (sigKeyBlock.useRsa) { +#ifndef NO_RSA c32toa(sigKeyBlock.sk.rsa.eSz + sigKeyBlock.sk.rsa.ePad, output + idx); idx += LENGTH_SZ; @@ -6617,6 +6649,7 @@ int SendKexDhReply(WOLFSSH* ssh) if (sigKeyBlock.sk.rsa.nPad) output[idx++] = 0; WMEMCPY(output + idx, sigKeyBlock.sk.rsa.n, sigKeyBlock.sk.rsa.nSz); idx += sigKeyBlock.sk.rsa.nSz; +#endif } else { c32toa(sigKeyBlock.sk.ecc.primeNameSz, output + idx); @@ -7282,6 +7315,7 @@ typedef struct WS_KeySignature { const char *name; word32 nameSz; union { +#ifndef NO_RSA struct { RsaKey key; byte e[256]; @@ -7291,6 +7325,7 @@ typedef struct WS_KeySignature { word32 nSz; byte nPad; } rsa; +#endif struct { ecc_key key; word32 keyBlobSz; @@ -7352,6 +7387,7 @@ static int BuildUserAuthRequestPassword(WOLFSSH* ssh, } +#ifndef NO_RSA static int PrepareUserAuthRequestRsa(WOLFSSH* ssh, word32* payloadSz, const WS_UserAuthData* authData, WS_KeySignature* keySig) { @@ -7504,6 +7540,7 @@ static int BuildUserAuthRequestRsa(WOLFSSH* ssh, return ret; } +#endif static int PrepareUserAuthRequestEcc(WOLFSSH* ssh, word32* payloadSz, @@ -7725,8 +7762,11 @@ static int PrepareUserAuthRequestPublicKey(WOLFSSH* ssh, word32* payloadSz, authData->sf.publicKey.publicKeySz; } - if (keySig->keySigId == ID_SSH_RSA) + if (keySig->keySigId == ID_SSH_RSA) { +#ifndef NO_RSA ret = PrepareUserAuthRequestRsa(ssh, payloadSz, authData, keySig); +#endif + } else if (keySig->keySigId == ID_ECDSA_SHA2_NISTP256 || keySig->keySigId == ID_ECDSA_SHA2_NISTP384 || keySig->keySigId == ID_ECDSA_SHA2_NISTP521) @@ -7766,9 +7806,12 @@ static int BuildUserAuthRequestPublicKey(WOLFSSH* ssh, begin += pk->publicKeySz; if (pk->hasSignature) { - if (keySig->keySigId == ID_SSH_RSA) + if (keySig->keySigId == ID_SSH_RSA) { +#ifndef NO_RSA ret = BuildUserAuthRequestRsa(ssh, output, &begin, authData, sigStart, sigStartIdx, keySig); +#endif + } else if (keySig->keySigId == ID_ECDSA_SHA2_NISTP256 || keySig->keySigId == ID_ECDSA_SHA2_NISTP384 || keySig->keySigId == ID_ECDSA_SHA2_NISTP521) @@ -7789,8 +7832,11 @@ static int BuildUserAuthRequestPublicKey(WOLFSSH* ssh, static void CleanupUserAuthRequestPublicKey(WS_KeySignature* keySig) { if (keySig != NULL) { - if (keySig->keySigId == ID_SSH_RSA) + if (keySig->keySigId == ID_SSH_RSA) { +#ifndef NO_RSA wc_FreeRsaKey(&keySig->ks.rsa.key); +#endif + } else wc_ecc_free(&keySig->ks.ecc.key); } diff --git a/src/keygen.c b/src/keygen.c index 589bc24..9beaf77 100644 --- a/src/keygen.c +++ b/src/keygen.c @@ -57,6 +57,8 @@ int wolfSSH_MakeRsaKey(byte* out, word32 outSz, word32 size, word32 e) { +#ifndef NO_RSA + int ret = WS_SUCCESS; WC_RNG rng; @@ -105,6 +107,13 @@ int wolfSSH_MakeRsaKey(byte* out, word32 outSz, WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_MakeRsaKey(), ret = %d", ret); return ret; +#else + (void)out; + (void)outSz; + (void)size; + (void)e; + return WS_NOT_COMPILED; +#endif } diff --git a/src/ssh.c b/src/ssh.c index 985d24a..eee08c3 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -1441,7 +1441,9 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format, else if (format == WOLFSSH_FORMAT_ASN1) { byte* newKey; union { - RsaKey rsa; + #ifndef NO_RSA + RsaKey rsa; + #endif ecc_key ecc; } testKey; word32 scratch = 0; @@ -1459,7 +1461,7 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format, } *outSz = inSz; WMEMCPY(newKey, in, inSz); - +#ifndef NO_RSA /* TODO: This is copied and modified from a function in src/internal.c. This and that code should be combined into a single function. */ if (wc_InitRsaKey(&testKey.rsa, heap) < 0) @@ -1474,6 +1476,7 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format, *outTypeSz = (word32)WSTRLEN((const char*)*outType); } else { +#endif /* Couldn't decode as RSA testKey. Try decoding as ECC testKey. */ scratch = 0; if (wc_ecc_init_ex(&testKey.ecc, heap, INVALID_DEVID) != 0) @@ -1489,7 +1492,9 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format, } else return WS_BAD_FILE_E; +#ifndef NO_RSA } +#endif } else ret = WS_ERROR; diff --git a/tests/api.c b/tests/api.c index 39ed412..3e6b63d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -570,9 +570,10 @@ static void test_wolfSSH_CTX_UsePrivateKey_buffer(void) AssertNotNull(ctx->privateKey); AssertIntNE(0, ctx->privateKeySz); AssertIntEQ(ECC_SECP256R1, ctx->useEcc); + +#ifndef NO_RSA lastKey = ctx->privateKey; lastKeySz = ctx->privateKeySz; - AssertIntEQ(WS_SUCCESS, wolfSSH_CTX_UsePrivateKey_buffer(ctx, rsaKey, rsaKeySz, TEST_GOOD_FORMAT_ASN1)); @@ -581,6 +582,10 @@ static void test_wolfSSH_CTX_UsePrivateKey_buffer(void) AssertIntEQ(0, ctx->useEcc); AssertIntEQ(0, (lastKey == ctx->privateKey)); AssertIntNE(lastKeySz, ctx->privateKeySz); +#else + (void)lastKey; + (void)lastKeySz; +#endif wolfSSH_CTX_free(ctx); FreeBins(eccKey, rsaKey, NULL, NULL);