msvcp90: Only define virtual function callers in base class.
[wine] / dlls / crypt32 / message.c
1 /*
2  * Copyright 2007 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <stdarg.h>
20 #include "windef.h"
21 #include "winbase.h"
22 #include "wincrypt.h"
23
24 #include "wine/debug.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
27
28 HCERTSTORE WINAPI CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType,
29  HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const BYTE* pbSignedBlob,
30  DWORD cbSignedBlob)
31 {
32     CRYPT_DATA_BLOB blob = { cbSignedBlob, (LPBYTE)pbSignedBlob };
33
34     TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType, hCryptProv,
35      dwFlags, pbSignedBlob, cbSignedBlob);
36
37     return CertOpenStore(CERT_STORE_PROV_PKCS7, dwMsgAndCertEncodingType,
38      hCryptProv, dwFlags, &blob);
39 }
40
41 LONG WINAPI CryptGetMessageSignerCount(DWORD dwMsgEncodingType,
42  const BYTE *pbSignedBlob, DWORD cbSignedBlob)
43 {
44     HCRYPTMSG msg;
45     LONG count = -1;
46
47     TRACE("(%08x, %p, %d)\n", dwMsgEncodingType, pbSignedBlob, cbSignedBlob);
48
49     msg = CryptMsgOpenToDecode(dwMsgEncodingType, 0, 0, 0, NULL, NULL);
50     if (msg)
51     {
52         if (CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE))
53         {
54             DWORD size = sizeof(count);
55
56             CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &count, &size);
57         }
58         CryptMsgClose(msg);
59     }
60     return count;
61 }
62
63 static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg,
64  DWORD dwSignerIndex)
65 {
66     CERT_INFO *certInfo = NULL;
67     DWORD size;
68
69     if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL,
70      &size))
71     {
72         certInfo = CryptMemAlloc(size);
73         if (certInfo)
74         {
75             if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM,
76              dwSignerIndex, certInfo, &size))
77             {
78                 CryptMemFree(certInfo);
79                 certInfo = NULL;
80             }
81         }
82     }
83     else
84         SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE);
85     return certInfo;
86 }
87
88 static PCCERT_CONTEXT WINAPI CRYPT_DefaultGetSignerCertificate(void *pvGetArg,
89  DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hMsgCertStore)
90 {
91     return CertFindCertificateInStore(hMsgCertStore, dwCertEncodingType, 0,
92      CERT_FIND_SUBJECT_CERT, pSignerId, NULL);
93 }
94
95 static inline PCCERT_CONTEXT CRYPT_GetSignerCertificate(HCRYPTMSG msg,
96  PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_INFO certInfo, HCERTSTORE store)
97 {
98     PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert;
99
100     if (pVerifyPara->pfnGetSignerCertificate)
101         getCert = pVerifyPara->pfnGetSignerCertificate;
102     else
103         getCert = CRYPT_DefaultGetSignerCertificate;
104     return getCert(pVerifyPara->pvGetArg,
105      pVerifyPara->dwMsgAndCertEncodingType, certInfo, store);
106 }
107
108 BOOL WINAPI CryptVerifyDetachedMessageSignature(
109  PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex,
110  const BYTE *pbDetachedSignBlob, DWORD cbDetachedSignBlob, DWORD cToBeSigned,
111  const BYTE *rgpbToBeSigned[], DWORD rgcbToBeSigned[],
112  PCCERT_CONTEXT *ppSignerCert)
113 {
114     BOOL ret = FALSE;
115     HCRYPTMSG msg;
116
117     TRACE("(%p, %d, %p, %d, %d, %p, %p, %p)\n", pVerifyPara, dwSignerIndex,
118      pbDetachedSignBlob, cbDetachedSignBlob, cToBeSigned, rgpbToBeSigned,
119      rgcbToBeSigned, ppSignerCert);
120
121     if (ppSignerCert)
122         *ppSignerCert = NULL;
123     if (!pVerifyPara ||
124      pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
125      GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
126      PKCS_7_ASN_ENCODING)
127     {
128         SetLastError(E_INVALIDARG);
129         return FALSE;
130     }
131
132     msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType,
133      CMSG_DETACHED_FLAG, 0, pVerifyPara->hCryptProv, NULL, NULL);
134     if (msg)
135     {
136         ret = CryptMsgUpdate(msg, pbDetachedSignBlob, cbDetachedSignBlob, TRUE);
137         if (ret)
138         {
139             DWORD i;
140
141             for (i = 0; ret && i < cToBeSigned; i++)
142                 ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i],
143                  i == cToBeSigned - 1);
144         }
145         if (ret)
146         {
147             CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
148              dwSignerIndex);
149
150             ret = FALSE;
151             if (certInfo)
152             {
153                 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
154                  pVerifyPara->dwMsgAndCertEncodingType,
155                  pVerifyPara->hCryptProv, 0, msg);
156
157                 if (store)
158                 {
159                     PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
160                      msg, pVerifyPara, certInfo, store);
161
162                     if (cert)
163                     {
164                         ret = CryptMsgControl(msg, 0,
165                          CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
166                         if (ret && ppSignerCert)
167                             *ppSignerCert = cert;
168                         else
169                             CertFreeCertificateContext(cert);
170                     }
171                     else
172                         SetLastError(CRYPT_E_NOT_FOUND);
173                     CertCloseStore(store, 0);
174                 }
175                 CryptMemFree(certInfo);
176             }
177         }
178         CryptMsgClose(msg);
179     }
180     TRACE("returning %d\n", ret);
181     return ret;
182 }
183
184 BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
185  DWORD dwSignerIndex, const BYTE* pbSignedBlob, DWORD cbSignedBlob,
186  BYTE* pbDecoded, DWORD* pcbDecoded, PCCERT_CONTEXT* ppSignerCert)
187 {
188     BOOL ret = FALSE;
189     HCRYPTMSG msg;
190
191     TRACE("(%p, %d, %p, %d, %p, %p, %p)\n",
192      pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob,
193      pbDecoded, pcbDecoded, ppSignerCert);
194
195     if (ppSignerCert)
196         *ppSignerCert = NULL;
197     if (!pVerifyPara ||
198      pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
199      GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
200      PKCS_7_ASN_ENCODING)
201     {
202         if(pcbDecoded)
203             *pcbDecoded = 0;
204         SetLastError(E_INVALIDARG);
205         return FALSE;
206     }
207
208     msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType, 0, 0,
209      pVerifyPara->hCryptProv, NULL, NULL);
210     if (msg)
211     {
212         ret = CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE);
213         if (ret)
214         {
215             CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
216              dwSignerIndex);
217
218             ret = FALSE;
219             if (certInfo)
220             {
221                 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
222                  pVerifyPara->dwMsgAndCertEncodingType,
223                  pVerifyPara->hCryptProv, 0, msg);
224
225                 if (store)
226                 {
227                     PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
228                      msg, pVerifyPara, certInfo, store);
229
230                     if (cert)
231                     {
232                         ret = CryptMsgControl(msg, 0,
233                          CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
234                         if (ret && ppSignerCert)
235                             *ppSignerCert = cert;
236                         else
237                             CertFreeCertificateContext(cert);
238                     }
239                     CertCloseStore(store, 0);
240                 }
241             }
242             CryptMemFree(certInfo);
243         }
244         if (ret)
245         {
246             /* The caller is expected to pass a valid pointer to pcbDecoded
247              * when the message verifies successfully.
248              */
249             if (pcbDecoded)
250                 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded,
251                  pcbDecoded);
252             else
253             {
254                 SetLastError(CRYPT_E_NOT_FOUND);
255                 ret = FALSE;
256             }
257         }
258         CryptMsgClose(msg);
259     }
260     if(!ret && pcbDecoded)
261         *pcbDecoded = 0;
262     TRACE("returning %d\n", ret);
263     return ret;
264 }
265
266 BOOL WINAPI CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara,
267  BOOL fDetachedHash, DWORD cToBeHashed, const BYTE *rgpbToBeHashed[],
268  DWORD rgcbToBeHashed[], BYTE *pbHashedBlob, DWORD *pcbHashedBlob,
269  BYTE *pbComputedHash, DWORD *pcbComputedHash)
270 {
271     DWORD i, flags;
272     BOOL ret = FALSE;
273     HCRYPTMSG msg;
274     CMSG_HASHED_ENCODE_INFO info;
275
276     TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara, fDetachedHash,
277      cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, pcbHashedBlob,
278      pbComputedHash, pcbComputedHash);
279
280     if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
281     {
282         SetLastError(E_INVALIDARG);
283         return FALSE;
284     }
285     /* Native seems to ignore any encoding type other than the expected
286      * PKCS_7_ASN_ENCODING
287      */
288     if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
289      PKCS_7_ASN_ENCODING)
290         return TRUE;
291     /* Native also seems to do nothing if the output parameter isn't given */
292     if (!pcbHashedBlob)
293         return TRUE;
294
295     flags = fDetachedHash ? CMSG_DETACHED_FLAG : 0;
296     memset(&info, 0, sizeof(info));
297     info.cbSize = sizeof(info);
298     info.hCryptProv = pHashPara->hCryptProv;
299     memcpy(&info.HashAlgorithm, &pHashPara->HashAlgorithm,
300      sizeof(info.HashAlgorithm));
301     info.pvHashAuxInfo = pHashPara->pvHashAuxInfo;
302     msg = CryptMsgOpenToEncode(pHashPara->dwMsgEncodingType, flags, CMSG_HASHED,
303      &info, NULL, NULL);
304     if (msg)
305     {
306         for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++)
307             ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i], i == cToBeHashed - 1);
308         if (ret)
309         {
310             ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob,
311              pcbHashedBlob);
312             if (ret && pcbComputedHash)
313                 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
314                  pbComputedHash, pcbComputedHash);
315         }
316         CryptMsgClose(msg);
317     }
318     return ret;
319 }
320
321 BOOL WINAPI CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
322  BYTE *pbDetachedHashBlob, DWORD cbDetachedHashBlob, DWORD cToBeHashed,
323  const BYTE *rgpbToBeHashed[], DWORD rgcbToBeHashed[], BYTE *pbComputedHash,
324  DWORD *pcbComputedHash)
325 {
326     HCRYPTMSG msg;
327     BOOL ret = FALSE;
328
329     TRACE("(%p, %p, %d, %d, %p, %p, %p, %p)\n", pHashPara, pbDetachedHashBlob,
330      cbDetachedHashBlob, cToBeHashed, rgpbToBeHashed, rgcbToBeHashed,
331      pbComputedHash, pcbComputedHash);
332
333     if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
334     {
335         SetLastError(E_INVALIDARG);
336         return FALSE;
337     }
338     if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
339      PKCS_7_ASN_ENCODING)
340     {
341         SetLastError(E_INVALIDARG);
342         return FALSE;
343     }
344     msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, CMSG_DETACHED_FLAG,
345      0, pHashPara->hCryptProv, NULL, NULL);
346     if (msg)
347     {
348         DWORD i;
349
350         ret = CryptMsgUpdate(msg, pbDetachedHashBlob, cbDetachedHashBlob, TRUE);
351         if (ret)
352         {
353             if (cToBeHashed)
354             {
355                 for (i = 0; ret && i < cToBeHashed; i++)
356                 {
357                     ret = CryptMsgUpdate(msg, rgpbToBeHashed[i],
358                      rgcbToBeHashed[i], i == cToBeHashed - 1);
359                 }
360             }
361             else
362                 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
363         }
364         if (ret)
365         {
366             ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
367             if (ret && pcbComputedHash)
368                 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
369                  pbComputedHash, pcbComputedHash);
370         }
371         CryptMsgClose(msg);
372     }
373     return ret;
374 }
375
376 BOOL WINAPI CryptVerifyMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
377  BYTE *pbHashedBlob, DWORD cbHashedBlob, BYTE *pbToBeHashed,
378  DWORD *pcbToBeHashed, BYTE *pbComputedHash, DWORD *pcbComputedHash)
379 {
380     HCRYPTMSG msg;
381     BOOL ret = FALSE;
382
383     TRACE("(%p, %p, %d, %p, %p, %p, %p)\n", pHashPara, pbHashedBlob,
384      cbHashedBlob, pbToBeHashed, pcbToBeHashed, pbComputedHash,
385      pcbComputedHash);
386
387     if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
388     {
389         SetLastError(E_INVALIDARG);
390         return FALSE;
391     }
392     if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
393      PKCS_7_ASN_ENCODING)
394     {
395         SetLastError(E_INVALIDARG);
396         return FALSE;
397     }
398     msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, 0, 0,
399      pHashPara->hCryptProv, NULL, NULL);
400     if (msg)
401     {
402         ret = CryptMsgUpdate(msg, pbHashedBlob, cbHashedBlob, TRUE);
403         if (ret)
404         {
405             ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
406             if (ret && pcbToBeHashed)
407                 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0,
408                  pbToBeHashed, pcbToBeHashed);
409             if (ret && pcbComputedHash)
410                 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
411                  pbComputedHash, pcbComputedHash);
412         }
413         CryptMsgClose(msg);
414     }
415     return ret;
416 }
417
418 BOOL WINAPI CryptSignMessage(PCRYPT_SIGN_MESSAGE_PARA pSignPara,
419  BOOL fDetachedSignature, DWORD cToBeSigned, const BYTE *rgpbToBeSigned[],
420  DWORD rgcbToBeSigned[], BYTE *pbSignedBlob, DWORD *pcbSignedBlob)
421 {
422     HCRYPTPROV hCryptProv;
423     BOOL ret, freeProv = FALSE;
424     DWORD i, keySpec;
425     PCERT_BLOB certBlob = NULL;
426     PCRL_BLOB crlBlob = NULL;
427     CMSG_SIGNED_ENCODE_INFO signInfo;
428     CMSG_SIGNER_ENCODE_INFO signer;
429     HCRYPTMSG msg = 0;
430
431     TRACE("(%p, %d, %d, %p, %p, %p, %p)\n", pSignPara, fDetachedSignature,
432      cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, pbSignedBlob, pcbSignedBlob);
433
434     if (pSignPara->cbSize != sizeof(CRYPT_SIGN_MESSAGE_PARA) ||
435      GET_CMSG_ENCODING_TYPE(pSignPara->dwMsgEncodingType) !=
436      PKCS_7_ASN_ENCODING)
437     {
438         *pcbSignedBlob = 0;
439         SetLastError(E_INVALIDARG);
440         return FALSE;
441     }
442     if (!pSignPara->pSigningCert)
443         return TRUE;
444
445     ret = CryptAcquireCertificatePrivateKey(pSignPara->pSigningCert,
446      CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hCryptProv, &keySpec, &freeProv);
447     if (!ret)
448         return FALSE;
449
450     memset(&signer, 0, sizeof(signer));
451     signer.cbSize = sizeof(signer);
452     signer.pCertInfo = pSignPara->pSigningCert->pCertInfo;
453     signer.hCryptProv = hCryptProv;
454     signer.dwKeySpec = keySpec;
455     signer.HashAlgorithm = pSignPara->HashAlgorithm;
456     signer.pvHashAuxInfo = pSignPara->pvHashAuxInfo;
457     signer.cAuthAttr = pSignPara->cAuthAttr;
458     signer.rgAuthAttr = pSignPara->rgAuthAttr;
459     signer.cUnauthAttr = pSignPara->cUnauthAttr;
460     signer.rgUnauthAttr = pSignPara->rgUnauthAttr;
461
462     memset(&signInfo, 0, sizeof(signInfo));
463     signInfo.cbSize = sizeof(signInfo);
464     signInfo.cSigners = 1;
465     signInfo.rgSigners = &signer;
466
467     if (pSignPara->cMsgCert)
468     {
469         certBlob = CryptMemAlloc(sizeof(CERT_BLOB) * pSignPara->cMsgCert);
470         if (certBlob)
471         {
472             for (i = 0; i < pSignPara->cMsgCert; ++i)
473             {
474                 certBlob[i].cbData = pSignPara->rgpMsgCert[i]->cbCertEncoded;
475                 certBlob[i].pbData = pSignPara->rgpMsgCert[i]->pbCertEncoded;
476             }
477             signInfo.cCertEncoded = pSignPara->cMsgCert;
478             signInfo.rgCertEncoded = certBlob;
479         }
480         else
481             ret = FALSE;
482     }
483     if (pSignPara->cMsgCrl)
484     {
485         crlBlob = CryptMemAlloc(sizeof(CRL_BLOB) * pSignPara->cMsgCrl);
486         if (crlBlob)
487         {
488             for (i = 0; i < pSignPara->cMsgCrl; ++i)
489             {
490                 crlBlob[i].cbData = pSignPara->rgpMsgCrl[i]->cbCrlEncoded;
491                 crlBlob[i].pbData = pSignPara->rgpMsgCrl[i]->pbCrlEncoded;
492             }
493             signInfo.cCrlEncoded = pSignPara->cMsgCrl;
494             signInfo.rgCrlEncoded = crlBlob;
495         }
496         else
497             ret = FALSE;
498     }
499     if (pSignPara->dwFlags || pSignPara->dwInnerContentType)
500         FIXME("unimplemented feature\n");
501
502     if (ret)
503         msg = CryptMsgOpenToEncode(pSignPara->dwMsgEncodingType,
504          fDetachedSignature ? CMSG_DETACHED_FLAG : 0, CMSG_SIGNED, &signInfo,
505          NULL, NULL);
506     if (msg)
507     {
508         if (cToBeSigned)
509         {
510             for (i = 0; ret && i < cToBeSigned; ++i)
511             {
512                 ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i],
513                  i == cToBeSigned - 1);
514             }
515         }
516         else
517             ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
518         if (ret)
519             ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbSignedBlob,
520              pcbSignedBlob);
521         CryptMsgClose(msg);
522     }
523     else
524         ret = FALSE;
525
526     CryptMemFree(crlBlob);
527     CryptMemFree(certBlob);
528     if (freeProv)
529         CryptReleaseContext(hCryptProv, 0);
530     return ret;
531 }
532
533 BOOL WINAPI CryptEncryptMessage(PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
534  DWORD cRecipientCert, PCCERT_CONTEXT rgpRecipientCert[],
535  const BYTE *pbToBeEncrypted, DWORD cbToBeEncrypted, BYTE *pbEncryptedBlob,
536  DWORD *pcbEncryptedBlob)
537 {
538     BOOL ret = TRUE;
539     DWORD i;
540     PCERT_INFO *certInfo = NULL;
541     CMSG_ENVELOPED_ENCODE_INFO envelopedInfo;
542     HCRYPTMSG msg = 0;
543
544     TRACE("(%p, %d, %p, %p, %d, %p, %p)\n", pEncryptPara, cRecipientCert,
545      rgpRecipientCert, pbToBeEncrypted, cbToBeEncrypted, pbEncryptedBlob,
546      pcbEncryptedBlob);
547
548     if (pEncryptPara->cbSize != sizeof(CRYPT_ENCRYPT_MESSAGE_PARA) ||
549      GET_CMSG_ENCODING_TYPE(pEncryptPara->dwMsgEncodingType) !=
550      PKCS_7_ASN_ENCODING)
551     {
552         *pcbEncryptedBlob = 0;
553         SetLastError(E_INVALIDARG);
554         return FALSE;
555     }
556
557     memset(&envelopedInfo, 0, sizeof(envelopedInfo));
558     envelopedInfo.cbSize = sizeof(envelopedInfo);
559     envelopedInfo.hCryptProv = pEncryptPara->hCryptProv;
560     envelopedInfo.ContentEncryptionAlgorithm =
561      pEncryptPara->ContentEncryptionAlgorithm;
562     envelopedInfo.pvEncryptionAuxInfo = pEncryptPara->pvEncryptionAuxInfo;
563
564     if (cRecipientCert)
565     {
566         certInfo = CryptMemAlloc(sizeof(PCERT_INFO) * cRecipientCert);
567         if (certInfo)
568         {
569             for (i = 0; i < cRecipientCert; ++i)
570                 certInfo[i] = rgpRecipientCert[i]->pCertInfo;
571             envelopedInfo.cRecipients = cRecipientCert;
572             envelopedInfo.rgpRecipientCert = certInfo;
573         }
574         else
575             ret = FALSE;
576     }
577
578     if (ret)
579         msg = CryptMsgOpenToEncode(pEncryptPara->dwMsgEncodingType, 0,
580          CMSG_ENVELOPED, &envelopedInfo, NULL, NULL);
581     if (msg)
582     {
583         ret = CryptMsgUpdate(msg, pbToBeEncrypted, cbToBeEncrypted, TRUE);
584         if (ret)
585             ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbEncryptedBlob,
586              pcbEncryptedBlob);
587         CryptMsgClose(msg);
588     }
589     else
590         ret = FALSE;
591
592     CryptMemFree(certInfo);
593     if (!ret) *pcbEncryptedBlob = 0;
594     return ret;
595 }