Skip to content

Commit

Permalink
Merge pull request wolfSSL#709 from ejohnstown/rsa-verify-refactor
Browse files Browse the repository at this point in the history
RSA Verify Refactor
  • Loading branch information
dgarske authored and jefferyq2 committed Oct 18, 2024
1 parent 29953b3 commit 807df4d
Showing 1 changed file with 250 additions and 0 deletions.
250 changes: 250 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -6346,6 +6346,20 @@ static int DoUnimplemented(WOLFSSH* ssh,

WOLFSSH_UNUSED(ssh);
WOLFSSH_UNUSED(len);
const byte* publicKeyType;
const byte* sig;
word32 publicKeyTypeSz = 0;
word32 sigSz;
word32 encDigestSz;
word32 i = 0;
int ret = WS_SUCCESS;
#ifdef WOLFSSH_SMALL_STACK
byte* encDigest = NULL;
RsaKey* key = NULL;
#else
byte encDigest[MAX_ENCODED_SIG_SZ];
RsaKey key[1];
#endif

ato32(buf + begin, &seq);
begin += UINT32_SZ;
Expand All @@ -6357,6 +6371,26 @@ static int DoUnimplemented(WOLFSSH* ssh,
return WS_SUCCESS;
}

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

if (ret == WS_SUCCESS) {
ret = wc_InitRsaKey(key, ssh->ctx->heap);
if (ret == 0) {
ret = WS_SUCCESS;
}
}

static int DoDisconnect(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
{
Expand Down Expand Up @@ -6415,6 +6449,29 @@ static int DoDisconnect(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)

return WS_SUCCESS;
}
/* Load up the key. */
if (ret == WS_SUCCESS) {
const byte* n = NULL;
word32 nSz = 0;
const byte* e = NULL;
word32 eSz = 0;

if (ret == WS_SUCCESS) {
ret = GetMpint(&eSz, &e, pk->publicKey, pk->publicKeySz, &i);
}

if (ret == WS_SUCCESS) {
ret = GetMpint(&nSz, &n, pk->publicKey, pk->publicKeySz, &i);
}

if (ret == WS_SUCCESS) {
ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key);
if (ret != 0) {
WLOG(WS_LOG_DEBUG, "Could not decode public key");
ret = WS_CRYPTO_FAILED;
}
}
}


static int DoServiceRequest(WOLFSSH* ssh,
Expand Down Expand Up @@ -6443,6 +6500,25 @@ static int DoServiceRequest(WOLFSSH* ssh,
ssh->clientState = CLIENT_USERAUTH_REQUEST_DONE;

return WS_SUCCESS;
if (ret == WS_SUCCESS) {
encDigestSz = wc_EncodeSignature(encDigest,
digest, digestSz, wc_HashGetOID(hashId));
ret = wolfSSH_RsaVerify(sig, sigSz, encDigest, encDigestSz,
key, ssh->ctx->heap, "DoUserAuthRequestRsa");
}

wc_FreeRsaKey(key);
#ifdef WOLFSSH_SMALL_STACK
if (key) {
WFREE(key, ssh->ctx->heap, DYNTYPE_PUBKEY);
}
if (encDigest) {
WFREE(encDigest, ssh->ctx->heap, DYNTYPE_BUFFER);
}
#endif

WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestRsa(), ret = %d", ret);
return ret;
}


Expand All @@ -6455,6 +6531,20 @@ static int DoServiceAccept(WOLFSSH* ssh,

ato32(buf + begin, &nameSz);
begin += LENGTH_SZ;
const byte* publicKeyType;
const byte* sig;
word32 publicKeyTypeSz = 0;
word32 sigSz;
word32 encDigestSz;
word32 i = 0;
int ret = WS_SUCCESS;
#ifdef WOLFSSH_SMALL_STACK
byte* encDigest = NULL;
RsaKey* key = NULL;
#else
byte encDigest[MAX_ENCODED_SIG_SZ];
RsaKey key[1];
#endif

if (begin + nameSz > len || nameSz >= WOLFSSH_MAX_NAMESZ) {
return WS_BUFFER_E;
Expand All @@ -6472,6 +6562,32 @@ static int DoServiceAccept(WOLFSSH* ssh,
return WS_SUCCESS;
}

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

if (ret == WS_SUCCESS) {
ret = wc_InitRsaKey(key, ssh->ctx->heap);
if (ret == 0) {
ret = WS_SUCCESS;
}
}

/* Load up the key. */
if (ret == WS_SUCCESS) {
byte* pub = NULL;
word32 pubSz;
DecodedCert cert;

static int DoExtInfoServerSigAlgs(WOLFSSH* ssh,
const byte* names, word32 namesSz)
Expand All @@ -6486,6 +6602,13 @@ static int DoExtInfoServerSigAlgs(WOLFSSH* ssh,
peerSigId = (byte*)WMALLOC(peerSigIdSz, ssh->ctx->heap, DYNTYPE_ID);
if (peerSigId == NULL) {
ret = WS_MEMORY_E;
if (ret == 0) {
i = 0;
ret = wc_RsaPublicKeyDecode(pub, &i, key, pubSz);
if (ret != 0) {
WLOG(WS_LOG_DEBUG, "Could not decode public key");
ret = WS_CRYPTO_FAILED;
}
}
}

Expand All @@ -6500,6 +6623,11 @@ static int DoExtInfoServerSigAlgs(WOLFSSH* ssh,

if (algoId == ID_UNKNOWN) {
ret = WS_MATCH_UA_KEY_ID_E;
if (ret == WS_SUCCESS) {
int keySz = wc_RsaEncryptSize(key) * 8;
if (keySz < 2048) {
WLOG(WS_LOG_DEBUG, "Key size too small (%d)", keySz);
ret = WS_CERT_KEY_SIZE_E;
}
}

Expand Down Expand Up @@ -6602,6 +6730,44 @@ static int DoUserAuthRequestNone(WOLFSSH* ssh, WS_UserAuthData* authData,
}

WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestNone(), ret = %d", ret);
i = 0;
/* Check that the signature's pubkey type matches the expected one. */
ret = GetStringRef(&publicKeyTypeSz, &publicKeyType,
pk->signature, pk->signatureSz, &i);
}

if (ret == WS_SUCCESS) {
if (publicKeyTypeSz != pk->publicKeyTypeSz &&
WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) != 0) {

WLOG(WS_LOG_DEBUG,
"Signature's type does not match public key type");
ret = WS_INVALID_ALGO_ID;
}
}

if (ret == WS_SUCCESS) {
ret = GetMpint(&sigSz, &sig, pk->signature, pk->signatureSz, &i);
}

if (ret == WS_SUCCESS) {
encDigestSz = wc_EncodeSignature(encDigest,
digest, digestSz, wc_HashGetOID(hashId));
ret = wolfSSH_RsaVerify(sig, sigSz, encDigest, encDigestSz,
key, ssh->ctx->heap, "DoUserAuthRequestRsaCert");
}

wc_FreeRsaKey(key);
#ifdef WOLFSSH_SMALL_STACK
if (key) {
WFREE(key, ssh->ctx->heap, DYNTYPE_PUBKEY);
}
if (encDigest) {
WFREE(encDigest, ssh->ctx->heap, DYNTYPE_BUFFER);
}
#endif

WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestRsaCert(), ret = %d", ret);
return ret;
}
#endif
Expand Down Expand Up @@ -11742,6 +11908,90 @@ static int KeyAgreeEcdhKyber1_server(WOLFSSH* ssh, byte hashId,
}

WLOG(WS_LOG_DEBUG, "Leaving KeyAgreeEcdhKyber1_server(), ret = %d", ret);
#ifndef WOLFSSH_NO_RSA
/*
* wolfSSH_RsaVerify
* sig - signature to verify
* sigSz - signature size
* encDigest - encoded digest for verification
* encDigestSz - encoded digest size
* 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(const byte *sig, word32 sigSz,
const byte* encDigest, word32 encDigestSz,
RsaKey* key, void* heap, const char* loc)
{
byte* checkSig = NULL;
int checkDigestSz;
word32 keySz;
int ret = WS_SUCCESS;
#ifdef WOLFSSH_SMALL_STACK
byte* checkDigest = NULL;
#else
byte checkDigest[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_TEMP);
if (checkDigest == NULL)
ret = WS_MEMORY_E;
}
#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) {
volatile int sizeCompare;
volatile int compare;

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_TEMP);
#endif
if (checkSig)
WFREE(checkSig, heap, DYNTYPE_TEMP);
return ret;
}
#else /* WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256 */
Expand Down

0 comments on commit 807df4d

Please sign in to comment.