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


int
mscrypto_rsa_decrypt(
    int len,
    const unsigned char *from,
    unsigned char *to,
    RSA *rsa,
    int padding,
    int pubkey
) {
    int outlen = -1;

    HCRYPTKEY hKey = (HCRYPTKEY)NULL;
    BYTE *pbData = NULL;
    DWORD dwDataLen = 0;

#ifdef MSCRYPTO_TRACE
fprintf(stderr, "TRACE[mscrypto] mscrypto_rsa_decrypt(len=%d,..., padding=%d, pubkey=%d):\n", len , padding, pubkey);
#endif

    if (!check_padding(padding, "mscrypto_rsa_decrypt"))
        return(-1);

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

    /* allocate buffer for message decryption block */
    pbData = malloc(len);
    if (pbData == NULL){
        MSCRYPTOerr(MSCRYPTO_F_DECRYPT, MSCRYPTO_R_INSUFFICIENT_MEMORY);
        goto done;
    }

    /* make it little endian */
    memcpy_rev(pbData, from, len);

    /* using host key, decrypt the message */
    dwDataLen = len;
    if (!CryptDecrypt(
        hKey,
        (HCRYPTHASH) NULL,
        (BOOL) TRUE /*Final*/,
        (DWORD) 0 /*dwFlags*/,
        pbData,
        &dwDataLen
    )) {
        MSCRYPTOerr(MSCRYPTO_F_DECRYPT, MSCRYPTO_R_W32ERR);
        MSCRYPTOw32err("CryptDecrypt fail");
        goto done;
    }

#if 1
    memcpy(to, pbData, (size_t) dwDataLen);
#else
    memcpy_rev(to, pbData, (size_t) dwDataLen);
#endif
    outlen = (int) dwDataLen;

done:
    if (pbData) free(pbData);

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