Skip to content

Commit

Permalink
RSA Verify Refactor
Browse files Browse the repository at this point in the history
1. Duplicated the function wolfSSH_RsaVerify() into
   wolfSSH_RsaVerify_2() to handle the whole verify process including
   wrapping the digest with the RSA wrapper.
2. If the signature to verify is short, pad it to the key length with
   leading zeros. Some implementations of SSH will prune leading zeros
   from an mpint value as a string for the signature.
3. Swapped one case of needing to verify a signature to use the new
   function.
Note: this is a WIP. Testing the new function, then reusing it where
needed.
  • Loading branch information
ejohnstown committed Jun 5, 2024
1 parent 9204ae7 commit 065ae01
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 60 deletions.
166 changes: 106 additions & 60 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -5798,10 +5798,6 @@ static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk,
enum wc_HashType hashId, byte* digest,
word32 digestSz)
{
enum wc_HashType enmhashId = hashId;
byte *checkDigest = NULL;
byte *encDigest = NULL;
int checkDigestSz;
const byte* publicKeyType;
word32 publicKeyTypeSz = 0;
const byte* n;
Expand All @@ -5814,10 +5810,6 @@ static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk,
int ret = WS_SUCCESS;
RsaKey *key_ptr = NULL;

#ifndef WOLFSSH_SMALL_STACK
byte s_checkDigest[MAX_ENCODED_SIG_SZ];
#endif

WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestRsa()");

if (ssh == NULL || ssh->ctx == NULL || pk == NULL || digest == NULL ||
Expand All @@ -5827,22 +5819,13 @@ static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk,
}

if (ret == WS_SUCCESS) {
#ifdef WOLFSSH_SMALL_STACK
checkDigest = (byte*)WMALLOC(MAX_ENCODED_SIG_SZ, ssh->ctx->heap,
DYNTYPE_BUFFER);
if (checkDigest == NULL)
ret = WS_MEMORY_E;
#else
checkDigest = s_checkDigest;
#endif
key_ptr = (RsaKey*)WMALLOC(sizeof(RsaKey), ssh->ctx->heap,
DYNTYPE_PUBKEY);
if (key_ptr == NULL)
ret = WS_MEMORY_E;
}

if (ret == WS_SUCCESS) {
WMEMSET(checkDigest, 0, MAX_ENCODED_SIG_SZ);
ret = wc_InitRsaKey(key_ptr, ssh->ctx->heap);
if (ret == 0) {
ret = WS_SUCCESS;
Expand Down Expand Up @@ -5903,55 +5886,14 @@ static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk,
}

if (ret == WS_SUCCESS) {
checkDigestSz = wc_RsaSSL_Verify(sig, sigSz, checkDigest,
MAX_ENCODED_SIG_SZ, key_ptr);
if (checkDigestSz <= 0) {
WLOG(WS_LOG_DEBUG, "Could not verify signature");
ret = WS_CRYPTO_FAILED;
}
ret = wolfSSH_RsaVerify_2(sig, sigSz, digest, digestSz, hashId,
key_ptr, ssh->ctx->heap, "DoUserAuthRequestRsa");
}

if (ret == WS_SUCCESS) {
word32 encDigestSz;
volatile int compare;
volatile int sizeCompare;
#ifdef WOLFSSH_SMALL_STACK
encDigest = (byte*)WMALLOC(MAX_ENCODED_SIG_SZ, ssh->ctx->heap,
DYNTYPE_BUFFER);
if (encDigest == NULL)
ret = WS_MEMORY_E;

if (ret == WS_SUCCESS)
#else
byte s_encDigest[MAX_ENCODED_SIG_SZ];
encDigest = s_encDigest;
#endif
{
WMEMSET(encDigest, 0, MAX_ENCODED_SIG_SZ);
encDigestSz = wc_EncodeSignature(encDigest, digest,
wc_HashGetDigestSize(enmhashId),
wc_HashGetOID(enmhashId));

compare = ConstantCompare(encDigest, checkDigest,
encDigestSz);
sizeCompare = encDigestSz != (word32)checkDigestSz;

if ((compare == 0) && (sizeCompare == 0))
ret = WS_SUCCESS;
else
ret = WS_RSA_E;
}
}
if (key_ptr != NULL) {
wc_FreeRsaKey(key_ptr);
WFREE(key_ptr, ssh->ctx->heap, DYNTYPE_PUBKEY);
}
#ifdef WOLFSSH_SMALL_STACK
if (checkDigest)
WFREE(checkDigest, ssh->ctx->heap, DYNTYPE_BUFFER);
if (encDigest)
WFREE(encDigest, ssh->ctx->heap, DYNTYPE_BUFFER);
#endif
WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestRsa(), ret = %d", ret);
return ret;
}
Expand Down Expand Up @@ -9866,6 +9808,110 @@ static INLINE byte SigTypeForId(byte id)


#ifndef WOLFSSH_NO_RSA
/*
* wolfSSH_RsaVerify_2
* sig - signature to verify
* sigSz - signature size
* digest - digest for verification
* digestSz - digest size
* digestId - ID of the digest type
* key - key used to sign and verify signature
* heap - allocation heap
* loc - calling function for logging
*
* Takes the provided digest of type digestId and converts it to an
* encoded digest. Then verifies the signature, comparing the output
* digest and compares it.
*/
int wolfSSH_RsaVerify_2(const byte *sig, word32 sigSz,
const byte* digest, word32 digestSz, byte digestId,
RsaKey* key, void* heap, const char* loc)
{
byte* checkSig = NULL;
byte* checkDigest = NULL;
byte* encDigest = NULL;
int checkDigestSz;
word32 encDigestSz;
word32 keySz;
volatile int compare;
volatile int sizeCompare;
int ret = WS_SUCCESS;
#ifndef WOLFSSH_SMALL_STACK
byte s_checkDigest[MAX_ENCODED_SIG_SZ];
byte s_encDigest[MAX_ENCODED_SIG_SZ];
#endif

keySz = (word32)wc_RsaEncryptSize(key);

if (ret == WS_SUCCESS) {
checkSig = (byte*)WMALLOC(keySz, heap, DYNTYPE_TEMP);
if (checkSig == NULL)
ret = WS_MEMORY_E;
}
#ifdef WOLFSSH_SMALL_STACK
if (ret == WS_SUCCESS) {
checkDigest = (byte*)WMALLOC(MAX_ENCODED_SIG_SZ, heap, DYNTYPE_BUFFER);
if (checkDigest == NULL)
ret = WS_MEMORY_E;
}
if (ret == WS_SUCCESS) {
encDigest = (byte*)WMALLOC(MAX_ENCODED_SIG_SZ, heap, DYNTYPE_BUFFER);
if (encDigest == NULL)
ret = WS_MEMORY_E;
}
#else
checkDigest = s_checkDigest;
encDigest = s_encDigest;
#endif

/* Normalize the peer's signature. Some SSH implementations remove
* leading zeros on the signatures they encode. We need to pad the
* front of the signature to the key size. */
if (ret == WS_SUCCESS) {
word32 offset;

if (keySz > sigSz) {
offset = keySz - sigSz;
}
else {
sigSz = keySz;
offset = 0;
}

WMEMSET(checkSig, 0, offset);
WMEMCPY(checkSig + offset, sig, sigSz);
}

if (ret == WS_SUCCESS) {
WMEMSET(encDigest, 0, MAX_ENCODED_SIG_SZ);

encDigestSz = wc_EncodeSignature(encDigest,
digest, digestSz, wc_HashGetOID(digestId));
checkDigestSz = wc_RsaSSL_Verify(checkSig, keySz,
checkDigest, MAX_ENCODED_SIG_SZ, key);

sizeCompare = checkDigestSz > 0
&& encDigestSz != (word32)checkDigestSz;
compare = ConstantCompare(encDigest, checkDigest, encDigestSz);

if (checkDigestSz < 0 || sizeCompare || compare) {
WLOG(WS_LOG_DEBUG, "%s: %s", loc, "Bad RSA Verify");
ret = WS_RSA_E;
}
}

#ifdef WOLFSSH_SMALL_STACK
if (checkDigest)
WFREE(checkDigest, heap, DYNTYPE_BUFFER);
if (encDigest)
WFREE(encDigest, heap, DYNTYPE_BUFFER);
#endif
if (checkSig)
WFREE(checkSig, heap, DYNTYPE_BUFFER);
return ret;
}


/*
* wolfSSH_RsaVerify
* sig - signature to verify
Expand Down
3 changes: 3 additions & 0 deletions wolfssh/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,9 @@ 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 int wolfSSH_RsaVerify_2(const byte *sig, word32 sigSz,
const byte* digest, word32 digestSz, byte digestId,
RsaKey* key, void* heap, const char* loc);
#endif
WOLFSSH_LOCAL void DumpOctetString(const byte*, word32);
WOLFSSH_LOCAL int wolfSSH_oct2dec(WOLFSSH* ssh, byte* oct, word32 octSz);
Expand Down

0 comments on commit 065ae01

Please sign in to comment.