/* $Id: mscrypto_rsa_verify.c,v 1.2 2005/01/30 18:48:22 rumen Exp $ */
#include <openssl/engine.h>
#include "mscrypto_err.h"
#include "mscrypto_int.h"


int/*bool*/
mscrypto_rsa_verify(
    int dtype,
    const unsigned char *m,
    unsigned int m_length,
    unsigned char *sigbuf,
    unsigned int siglen,
    const RSA *rsa
) {
    int ret = 0;

    MSCRYPTO_KEYCTX *keyctx;
    HCRYPTKEY hKey;
    HCRYPTHASH hHash = (HCRYPTHASH)NULL;
    BYTE* pbSignature = NULL;
    DWORD dwSigLen = siglen;

#ifdef MSCRYPTO_TRACE
fprintf(stderr, "TRACE[mscrypto] mscrypto_rsa_verify(dtype=%d,...):\n", dtype);
#endif

    keyctx = RSA_get_ex_data(rsa, 0);
    if (keyctx == NULL) {
        MSCRYPTOerr(MSCRYPTO_F_RSA_VERIFY, MSCRYPTO_R_MISSING_KEY_CONTEXT);
        goto done;
    }

    hKey = mscrypto_get_hKey(rsa, 1);
    if (hKey == (HCRYPTKEY)NULL) {
        MSCRYPTOerr(MSCRYPTO_F_RSA_VERIFY, MSCRYPTO_R_KEY_IS_NOT_SET);
        goto done;
    }

    hHash = mscrypto_create_hash(keyctx->hCryptProv, dtype, m, m_length);
    if (hHash == (HCRYPTHASH)NULL) {
        /*error is already set*/
        goto done;
    }

    pbSignature = malloc(siglen);
    if (pbSignature == NULL) {
        MSCRYPTOerr(MSCRYPTO_F_RSA_VERIFY, MSCRYPTO_R_INSUFFICIENT_MEMORY);
        goto done;
    }
    memcpy_rev(pbSignature, sigbuf, siglen);

    if (!CryptVerifySignature(
        hHash,
        pbSignature,
        dwSigLen,
        hKey,
        (LPCTSTR) NULL  /*sDescription*/,
        (DWORD) 0 /*dwFlags*/
    )) {
        MSCRYPTOerr(MSCRYPTO_F_RSA_VERIFY, MSCRYPTO_R_W32ERR);
        MSCRYPTOw32err("CryptVerifySignature fail");
        goto done;
    }

    ret = 1;

done:
    if (pbSignature) free(pbSignature);
    if (hHash) CryptDestroyHash(hHash);

#ifdef MSCRYPTO_TRACE
fprintf(stderr, "TRACE[mscrypto] mscrypto_rsa_verify()^ ret=%d\n", ret);
#endif
    return(ret);
}
