CAPI: creating pkcs7 signature from large data

From: G. Rodr?guez (hez0s0_at_yahoo.com)
Date: 12/01/03


Date: 1 Dec 2003 10:01:17 -0800

Hi, i've been using CAPICOM to build some S/MIME messages in p7
format. However, CAPICOM seems to be unable to work with streaming,
which makes it unacceptable to sign large amounts of data. So i moved
to CryptoAPI, and tried to run some CAPI samples with streaming
signatures. I finally made the sample to run with my smartcard, but
the data i get does not seem to be valid ASN1 information. Such data
is (b64-encoded):
MYHnMIHkAgEBMD4wNjELMAkGA1UEBhMCRVMxDTALBgNVBAoTBEZOTVQxGDAWBgNVBAsTD0ZOTVQgQ2xhc2UgMiBDQQIEPHNZBjANBgkqhkiG9w0BAQUF

I'd like to find a way to produce a message similar to CAPICOM
SignedData.sign. I can't find my mistake in the following C CAPI code:

void main(void){
  char szContentTotal[] = "Se firmara este mensaje partido en dos
trocitos.";
        char* pszContentTotal = szContentTotal;
        BYTE* pbContentTotal = (BYTE*) pszContentTotal;
        DWORD cbContentTotal = sizeof(pszContentTotal);
        char* pszProvider = "CeresCSP";
        HCRYPTPROV hCryptProv = NULL; // Handle returned here
        BOOL fReturn = FALSE;
        fReturn = CryptAcquireContext(&hCryptProv, NULL, pszProvider,
PROV_RSA_FULL, 0 );
        if(!fReturn) {
                printf("CryptAcquireContext failed");
                return;
        }
        
        HCERTSTORE hStoreHandle = NULL;
        hStoreHandle = CertOpenSystemStore(hCryptProv, "MY");
        if (!hStoreHandle) {
                printf( "Error Getting Store Handle");
                return;
        }

        PCCERT_CONTEXT pSignerCert = NULL;
        pSignerCert = GetMySignerCert(hStoreHandle);
        if(!pSignerCert)
        {
                printf( "Error Getting Signer Cert");
                return;
        }

        DWORD HashAlgSize;
        CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
        HashAlgSize = sizeof(HashAlgorithm);
        memset(&HashAlgorithm, 0, HashAlgSize);
        HashAlgorithm.pszObjId = szOID_RSA_SHA1RSA;

        CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
        memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
        SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
        SignerEncodeInfo.pCertInfo = pSignerCert->pCertInfo;
        SignerEncodeInfo.hCryptProv = hCryptProv;
        SignerEncodeInfo.dwKeySpec = AT_SIGNATURE;
        SignerEncodeInfo.HashAlgorithm = HashAlgorithm;
        SignerEncodeInfo.pvHashAuxInfo = NULL;

        CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[1];
        SignerEncodeInfoArray[0] = SignerEncodeInfo;
        
        CERT_BLOB SignerCertBlob;
        SignerCertBlob.cbData = pSignerCert->cbCertEncoded;
        SignerCertBlob.pbData = pSignerCert->pbCertEncoded;

        CERT_BLOB SignerCertBlobArray[1];
        SignerCertBlobArray[0] = SignerCertBlob;

        CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
        memset(&SignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
        SignedMsgEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
        SignedMsgEncodeInfo.cSigners = 1;
        SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray;
        SignedMsgEncodeInfo.cCertEncoded = 1;
        SignedMsgEncodeInfo.rgCertEncoded = SignerCertBlobArray;
        SignedMsgEncodeInfo.rgCrlEncoded = NULL;

        DWORD cbEncodedBlob;
        BYTE *pbEncodedBlob = NULL;

        printf("Total size: %d\n", cbContentTotal);
        cbEncodedBlob = CryptMsgCalculateEncodedLength( PKCS_7_ASN_ENCODING,
     // Msg encoding type
        0, // Flags
        CMSG_SIGNED, // Msg type
        &SignedMsgEncodeInfo, // Ptr. to struct.
        NULL, // Inner content ObjID
        cbContentTotal); // size of content
        if(0 == cbEncodedBlob) {
                printf("Getting cbEncodedBlob length failed\n");
                return;
        }else{
                printf("Se reservarán %d bytes\n", cbEncodedBlob);
        }

        pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob);
        if(NULL == pbEncodedBlob) {
                printf("Malloc failed\n");
                return;
        }

        HCRYPTMSG hMsg = NULL;
        CMSG_STREAM_INFO streamInfo;
        streamInfo.cbContent = cbContentTotal;
        streamInfo.pfnStreamOutput = CmsgStreamOutputCallback;
        streamInfo.pvArg = NULL;
        hMsg = CryptMsgOpenToEncode(
                                        PKCS_7_ASN_ENCODING,
                                        0,
                                        CMSG_SIGNED,
                                        &SignedMsgEncodeInfo,
                                        szOID_RSA_data,
                                        &streamInfo);
        if(NULL == hMsg) {
                printf("OpenToEncode failed\n");
                MyHandleError("Abriendo para codificar");
                free(pbEncodedBlob);
                return;
        }

        BOOL fResult;
        fResult = CryptMsgUpdate( hMsg, pbContentTotal, cbContentTotal,
TRUE); if(!fResult){
                printf("MsgUpdate failed: %d\n", GetLastError());
                free(pbEncodedBlob);
                MyHandleError("Haciendo el update del MSG1");
                return;
        }
        CertFreeCertificateContext(pSignerCert);
        CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
        CryptMsgClose(hMsg);
} //fin del main

BOOL WINAPI CmsgStreamOutputCallback(IN const void *pvArg, IN BYTE
*pbData, IN DWORD cbData, IN BOOL fFinal){
        if (fFinal){
                char *cResult = Encode64((char*) pbData);
                printf("Message encoded sucessfully: #%s#\n", cResult);
        }
        return TRUE;
} //fin del CmsgStreamOutputCallback

Thank you in advance.


Quantcast