From b97b6c73b8ed077ace725691b18b5e57d3fbda85 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 21 Dec 2023 12:05:15 -0800 Subject: [PATCH] RSA Verify 1. Added function wolfSSH_RsaVerify() which verifies the provided RSA signature with the provided key. 2. Call wolfSSH_RsaVerify() after all calls to wc_RsaSSL_Sign(). 3. Changed a comparison between an unsigned and 0 to == from <=. 4. Fixed a spot where we still tried to sign a digest when the call to wc_DigestFinal() failed. --- src/agent.c | 4 +++ src/internal.c | 89 ++++++++++++++++++++++++++++++++++++++-------- wolfssh/internal.h | 4 +++ 3 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/agent.c b/src/agent.c index f72b7185e..78fc73c06 100644 --- a/src/agent.c +++ b/src/agent.c @@ -701,6 +701,10 @@ static int SignHashRsa(WOLFSSH_AGENT_KEY_RSA* rawKey, enum wc_HashType hashType, WLOG(WS_LOG_DEBUG, "Bad RSA Sign"); ret = WS_RSA_E; } + else { + ret = wolfSSH_RsaVerify(sig, *sigSz, + encSig, encSigSz, &key, heap, "SignHashRsa"); + } } wc_FreeRsaKey(&key); diff --git a/src/internal.c b/src/internal.c index c68e136c0..7e9727cf6 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9422,6 +9422,47 @@ static INLINE byte SigTypeForId(byte id) } +#ifndef WOLFSSH_NO_RSA +/* + * wolfSSH_RsaVerify + * sig - signature to verify + * sigSz - signature to verify size + * digest - encoded digest for verification + * digestSz - encoded digest size + * key - key used to sign and verify signature + * heap - allocation heap + * loc - calling function for logging + */ +int wolfSSH_RsaVerify(byte *sig, word32 sigSz, + const byte* digest, word32 digestSz, + RsaKey* key, void* heap, const char* loc) +{ + byte* checkSig; + int ret = WS_SUCCESS; + + checkSig = (byte*)WMALLOC(sigSz, heap, DYNTYPE_TEMP); + if (checkSig == NULL) { + ret = WS_MEMORY_E; + } + else { + int checkSz; + + checkSz = wc_RsaSSL_VerifyInline(sig, sigSz, &checkSig, key); + if (checkSz < 0 + || (word32)checkSz != digestSz + || WMEMCMP(digest, checkSig, digestSz) != 0) { + WLOG(WS_LOG_DEBUG, "%s: %s", loc, "Bad RSA Sign Verify"); + ret = WS_RSA_E; + } + ForceZero(checkSig, sigSz); + WFREE(checkSig, heap, DYNTYPE_TEMP); + } + + return ret; +} +#endif /* WOLFSSH_NO_RSA */ + + /* SendKexDhReply() * It is also the funciton used for MSGID_KEXECDH_REPLY. The parameters * are analogous between the two messages. Where MSGID_KEXDH_REPLY has @@ -9932,7 +9973,7 @@ int SendKexDhReply(WOLFSSH* ssh) encSigSz = wc_EncodeSignature(encSig, digest, wc_HashGetDigestSize(sigHashId), wc_HashGetOID(sigHashId)); - if (encSigSz <= 0) { + if (encSigSz == 0) { WLOG(WS_LOG_DEBUG, "SendKexDhReply: Bad Encode Sig"); ret = WS_CRYPTO_FAILED; } @@ -9946,6 +9987,12 @@ int SendKexDhReply(WOLFSSH* ssh) WLOG(WS_LOG_DEBUG, "SendKexDhReply: Bad RSA Sign"); ret = WS_RSA_E; } + else { + ret = wolfSSH_RsaVerify(sig_ptr, sigSz, + encSig, encSigSz, + &sigKeyBlock_ptr->sk.rsa.key, + heap, "SendKexDhReply"); + } } #ifdef WOLFSSH_SMALL_STACK WFREE(encSig, heap, DYNTYPE_TEMP); @@ -11175,6 +11222,11 @@ static int BuildUserAuthRequestRsa(WOLFSSH* ssh, WLOG(WS_LOG_DEBUG, "SUAR: Bad RSA Sign"); ret = WS_RSA_E; } + else { + ret = wolfSSH_RsaVerify(output + begin, keySig->sigSz, + encDigest, encDigestSz, &keySig->ks.rsa.key, + ssh->ctx->heap, "SUAR"); + } } } @@ -11324,21 +11376,23 @@ static int BuildUserAuthRequestRsaCert(WOLFSSH* ssh, if (ret == WS_SUCCESS) ret = wc_HashFinal(&hash, hashId, digest); - c32toa(keySig->sigSz + 7 + LENGTH_SZ * 2, output + begin); - begin += LENGTH_SZ; - c32toa(7, output + begin); - begin += LENGTH_SZ; - WMEMCPY(output + begin, "ssh-rsa", 7); - begin += 7; - c32toa(keySig->sigSz, output + begin); - begin += LENGTH_SZ; - encDigestSz = wc_EncodeSignature(encDigest, digest, digestSz, - wc_HashGetOID(hashId)); - if (encDigestSz <= 0) { - WLOG(WS_LOG_DEBUG, "SUAR: Bad Encode Sig"); - ret = WS_CRYPTO_FAILED; + if (ret == WS_SUCCESS) { + c32toa(keySig->sigSz + 7 + LENGTH_SZ * 2, output + begin); + begin += LENGTH_SZ; + c32toa(7, output + begin); + begin += LENGTH_SZ; + WMEMCPY(output + begin, "ssh-rsa", 7); + begin += 7; + c32toa(keySig->sigSz, output + begin); + begin += LENGTH_SZ; + encDigestSz = wc_EncodeSignature(encDigest, digest, digestSz, + wc_HashGetOID(hashId)); + if (encDigestSz <= 0) { + WLOG(WS_LOG_DEBUG, "SUAR: Bad Encode Sig"); + ret = WS_CRYPTO_FAILED; + } } - else { + if (ret == WS_SUCCESS) { int sigSz; WLOG(WS_LOG_INFO, "Signing hash with RSA."); sigSz = wc_RsaSSL_Sign(encDigest, encDigestSz, @@ -11348,6 +11402,11 @@ static int BuildUserAuthRequestRsaCert(WOLFSSH* ssh, WLOG(WS_LOG_DEBUG, "SUAR: Bad RSA Sign"); ret = WS_RSA_E; } + else { + ret = wolfSSH_RsaVerify(output + begin, keySig->sigSz, + encDigest, encDigestSz, &keySig->ks.rsa.key, + ssh->ctx->heap, "SUAR"); + } } if (ret == WS_SUCCESS) diff --git a/wolfssh/internal.h b/wolfssh/internal.h index cb2a4dce3..3cd5b3776 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -36,6 +36,7 @@ #include #include #include +#include #ifdef WOLFSSH_SCP #include #endif @@ -1195,6 +1196,9 @@ WOLFSSH_LOCAL int wsScpSendCallback(WOLFSSH*, int, const char*, char*, word32, WOLFSSH_LOCAL int wolfSSH_CleanPath(WOLFSSH* ssh, char* in); +WOLFSSH_LOCAL int wolfSSH_RsaVerify(byte *sig, word32 sigSz, + const byte* digest, word32 digestSz, + RsaKey* key, void* heap, const char* loc); WOLFSSH_LOCAL void DumpOctetString(const byte*, word32); WOLFSSH_LOCAL int wolfSSH_oct2dec(WOLFSSH* ssh, byte* oct, word32 octSz); WOLFSSH_LOCAL void AddAssign64(word32*, word32);