Release 1.5.0.
[wine/multimedia.git] / dlls / crypt32 / message.c
blobe5b6f2a6bfba6476f3e34c2c264cbcc6124f66e5
1 /*
2 * Copyright 2007 Juan Lang
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.
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.
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
19 #include <stdarg.h>
20 #include "windef.h"
21 #include "winbase.h"
22 #include "wincrypt.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
28 HCERTSTORE WINAPI CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType,
29 HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const BYTE* pbSignedBlob,
30 DWORD cbSignedBlob)
32 CRYPT_DATA_BLOB blob = { cbSignedBlob, (LPBYTE)pbSignedBlob };
34 TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType, hCryptProv,
35 dwFlags, pbSignedBlob, cbSignedBlob);
37 return CertOpenStore(CERT_STORE_PROV_PKCS7, dwMsgAndCertEncodingType,
38 hCryptProv, dwFlags, &blob);
41 LONG WINAPI CryptGetMessageSignerCount(DWORD dwMsgEncodingType,
42 const BYTE *pbSignedBlob, DWORD cbSignedBlob)
44 HCRYPTMSG msg;
45 LONG count = -1;
47 TRACE("(%08x, %p, %d)\n", dwMsgEncodingType, pbSignedBlob, cbSignedBlob);
49 msg = CryptMsgOpenToDecode(dwMsgEncodingType, 0, 0, 0, NULL, NULL);
50 if (msg)
52 if (CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE))
54 DWORD size = sizeof(count);
56 CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &count, &size);
58 CryptMsgClose(msg);
60 return count;
63 static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg,
64 DWORD dwSignerIndex)
66 CERT_INFO *certInfo = NULL;
67 DWORD size;
69 if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL,
70 &size))
72 certInfo = CryptMemAlloc(size);
73 if (certInfo)
75 if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM,
76 dwSignerIndex, certInfo, &size))
78 CryptMemFree(certInfo);
79 certInfo = NULL;
83 else
84 SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE);
85 return certInfo;
88 static PCCERT_CONTEXT WINAPI CRYPT_DefaultGetSignerCertificate(void *pvGetArg,
89 DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hMsgCertStore)
91 return CertFindCertificateInStore(hMsgCertStore, dwCertEncodingType, 0,
92 CERT_FIND_SUBJECT_CERT, pSignerId, NULL);
95 static inline PCCERT_CONTEXT CRYPT_GetSignerCertificate(HCRYPTMSG msg,
96 PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_INFO certInfo, HCERTSTORE store)
98 PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert;
100 if (pVerifyPara->pfnGetSignerCertificate)
101 getCert = pVerifyPara->pfnGetSignerCertificate;
102 else
103 getCert = CRYPT_DefaultGetSignerCertificate;
104 return getCert(pVerifyPara->pvGetArg,
105 pVerifyPara->dwMsgAndCertEncodingType, certInfo, store);
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)
114 BOOL ret = FALSE;
115 HCRYPTMSG msg;
117 TRACE("(%p, %d, %p, %d, %d, %p, %p, %p)\n", pVerifyPara, dwSignerIndex,
118 pbDetachedSignBlob, cbDetachedSignBlob, cToBeSigned, rgpbToBeSigned,
119 rgcbToBeSigned, ppSignerCert);
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)
128 SetLastError(E_INVALIDARG);
129 return FALSE;
132 msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType,
133 CMSG_DETACHED_FLAG, 0, pVerifyPara->hCryptProv, NULL, NULL);
134 if (msg)
136 ret = CryptMsgUpdate(msg, pbDetachedSignBlob, cbDetachedSignBlob, TRUE);
137 if (ret)
139 DWORD i;
141 for (i = 0; ret && i < cToBeSigned; i++)
142 ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i],
143 i == cToBeSigned - 1 ? TRUE : FALSE);
145 if (ret)
147 CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
148 dwSignerIndex);
150 ret = FALSE;
151 if (certInfo)
153 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
154 pVerifyPara->dwMsgAndCertEncodingType,
155 pVerifyPara->hCryptProv, 0, msg);
157 if (store)
159 PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
160 msg, pVerifyPara, certInfo, store);
162 if (cert)
164 ret = CryptMsgControl(msg, 0,
165 CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
166 if (ret && ppSignerCert)
167 *ppSignerCert = cert;
168 else
169 CertFreeCertificateContext(cert);
171 else
172 SetLastError(CRYPT_E_NOT_FOUND);
173 CertCloseStore(store, 0);
175 CryptMemFree(certInfo);
178 CryptMsgClose(msg);
180 TRACE("returning %d\n", ret);
181 return ret;
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)
188 BOOL ret = FALSE;
189 HCRYPTMSG msg;
191 TRACE("(%p, %d, %p, %d, %p, %p, %p)\n",
192 pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob,
193 pbDecoded, pcbDecoded, ppSignerCert);
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)
202 if(pcbDecoded)
203 *pcbDecoded = 0;
204 SetLastError(E_INVALIDARG);
205 return FALSE;
208 msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType, 0, 0,
209 pVerifyPara->hCryptProv, NULL, NULL);
210 if (msg)
212 ret = CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE);
213 if (ret)
215 CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
216 dwSignerIndex);
218 ret = FALSE;
219 if (certInfo)
221 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
222 pVerifyPara->dwMsgAndCertEncodingType,
223 pVerifyPara->hCryptProv, 0, msg);
225 if (store)
227 PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
228 msg, pVerifyPara, certInfo, store);
230 if (cert)
232 ret = CryptMsgControl(msg, 0,
233 CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
234 if (ret && ppSignerCert)
235 *ppSignerCert = cert;
236 else
237 CertFreeCertificateContext(cert);
239 CertCloseStore(store, 0);
242 CryptMemFree(certInfo);
244 if (ret)
246 /* The caller is expected to pass a valid pointer to pcbDecoded
247 * when the message verifies successfully.
249 if (pcbDecoded)
250 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded,
251 pcbDecoded);
252 else
254 SetLastError(CRYPT_E_NOT_FOUND);
255 ret = FALSE;
258 CryptMsgClose(msg);
260 if(!ret && pcbDecoded)
261 *pcbDecoded = 0;
262 TRACE("returning %d\n", ret);
263 return ret;
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)
271 DWORD i, flags;
272 BOOL ret = FALSE;
273 HCRYPTMSG msg;
274 CMSG_HASHED_ENCODE_INFO info;
276 TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara, fDetachedHash,
277 cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, pcbHashedBlob,
278 pbComputedHash, pcbComputedHash);
280 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
282 SetLastError(E_INVALIDARG);
283 return FALSE;
285 /* Native seems to ignore any encoding type other than the expected
286 * PKCS_7_ASN_ENCODING
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;
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)
306 for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++)
307 ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i],
308 i == cToBeHashed - 1 ? TRUE : FALSE);
309 if (ret)
311 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob,
312 pcbHashedBlob);
313 if (ret && pcbComputedHash)
314 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
315 pbComputedHash, pcbComputedHash);
317 CryptMsgClose(msg);
319 return ret;
322 BOOL WINAPI CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
323 BYTE *pbDetachedHashBlob, DWORD cbDetachedHashBlob, DWORD cToBeHashed,
324 const BYTE *rgpbToBeHashed[], DWORD rgcbToBeHashed[], BYTE *pbComputedHash,
325 DWORD *pcbComputedHash)
327 HCRYPTMSG msg;
328 BOOL ret = FALSE;
330 TRACE("(%p, %p, %d, %d, %p, %p, %p, %p)\n", pHashPara, pbDetachedHashBlob,
331 cbDetachedHashBlob, cToBeHashed, rgpbToBeHashed, rgcbToBeHashed,
332 pbComputedHash, pcbComputedHash);
334 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
336 SetLastError(E_INVALIDARG);
337 return FALSE;
339 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
340 PKCS_7_ASN_ENCODING)
342 SetLastError(E_INVALIDARG);
343 return FALSE;
345 msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, CMSG_DETACHED_FLAG,
346 0, pHashPara->hCryptProv, NULL, NULL);
347 if (msg)
349 DWORD i;
351 ret = CryptMsgUpdate(msg, pbDetachedHashBlob, cbDetachedHashBlob, TRUE);
352 if (ret)
354 if (cToBeHashed)
356 for (i = 0; ret && i < cToBeHashed; i++)
358 ret = CryptMsgUpdate(msg, rgpbToBeHashed[i],
359 rgcbToBeHashed[i], i == cToBeHashed - 1 ? TRUE : FALSE);
362 else
363 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
365 if (ret)
367 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
368 if (ret && pcbComputedHash)
369 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
370 pbComputedHash, pcbComputedHash);
372 CryptMsgClose(msg);
374 return ret;
377 BOOL WINAPI CryptVerifyMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
378 BYTE *pbHashedBlob, DWORD cbHashedBlob, BYTE *pbToBeHashed,
379 DWORD *pcbToBeHashed, BYTE *pbComputedHash, DWORD *pcbComputedHash)
381 HCRYPTMSG msg;
382 BOOL ret = FALSE;
384 TRACE("(%p, %p, %d, %p, %p, %p, %p)\n", pHashPara, pbHashedBlob,
385 cbHashedBlob, pbToBeHashed, pcbToBeHashed, pbComputedHash,
386 pcbComputedHash);
388 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
390 SetLastError(E_INVALIDARG);
391 return FALSE;
393 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
394 PKCS_7_ASN_ENCODING)
396 SetLastError(E_INVALIDARG);
397 return FALSE;
399 msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, 0, 0,
400 pHashPara->hCryptProv, NULL, NULL);
401 if (msg)
403 ret = CryptMsgUpdate(msg, pbHashedBlob, cbHashedBlob, TRUE);
404 if (ret)
406 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
407 if (ret && pcbToBeHashed)
408 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0,
409 pbToBeHashed, pcbToBeHashed);
410 if (ret && pcbComputedHash)
411 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
412 pbComputedHash, pcbComputedHash);
414 CryptMsgClose(msg);
416 return ret;
419 BOOL WINAPI CryptSignMessage(PCRYPT_SIGN_MESSAGE_PARA pSignPara,
420 BOOL fDetachedSignature, DWORD cToBeSigned, const BYTE *rgpbToBeSigned[],
421 DWORD rgcbToBeSigned[], BYTE *pbSignedBlob, DWORD *pcbSignedBlob)
423 HCRYPTPROV hCryptProv;
424 BOOL ret, freeProv = FALSE;
425 DWORD i, keySpec;
426 PCERT_BLOB certBlob = NULL;
427 PCRL_BLOB crlBlob = NULL;
428 CMSG_SIGNED_ENCODE_INFO signInfo;
429 CMSG_SIGNER_ENCODE_INFO signer;
430 HCRYPTMSG msg = 0;
432 TRACE("(%p, %d, %d, %p, %p, %p, %p)\n", pSignPara, fDetachedSignature,
433 cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, pbSignedBlob, pcbSignedBlob);
435 if (pSignPara->cbSize != sizeof(CRYPT_SIGN_MESSAGE_PARA) ||
436 GET_CMSG_ENCODING_TYPE(pSignPara->dwMsgEncodingType) !=
437 PKCS_7_ASN_ENCODING)
439 *pcbSignedBlob = 0;
440 SetLastError(E_INVALIDARG);
441 return FALSE;
443 if (!pSignPara->pSigningCert)
444 return TRUE;
446 ret = CryptAcquireCertificatePrivateKey(pSignPara->pSigningCert,
447 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hCryptProv, &keySpec, &freeProv);
448 if (!ret)
449 return FALSE;
451 memset(&signer, 0, sizeof(signer));
452 signer.cbSize = sizeof(signer);
453 signer.pCertInfo = pSignPara->pSigningCert->pCertInfo;
454 signer.hCryptProv = hCryptProv;
455 signer.dwKeySpec = keySpec;
456 signer.HashAlgorithm = pSignPara->HashAlgorithm;
457 signer.pvHashAuxInfo = pSignPara->pvHashAuxInfo;
458 signer.cAuthAttr = pSignPara->cAuthAttr;
459 signer.rgAuthAttr = pSignPara->rgAuthAttr;
460 signer.cUnauthAttr = pSignPara->cUnauthAttr;
461 signer.rgUnauthAttr = pSignPara->rgUnauthAttr;
463 memset(&signInfo, 0, sizeof(signInfo));
464 signInfo.cbSize = sizeof(signInfo);
465 signInfo.cSigners = 1;
466 signInfo.rgSigners = &signer;
468 if (pSignPara->cMsgCert)
470 certBlob = CryptMemAlloc(sizeof(CERT_BLOB) * pSignPara->cMsgCert);
471 if (certBlob)
473 for (i = 0; i < pSignPara->cMsgCert; ++i)
475 certBlob[i].cbData = pSignPara->rgpMsgCert[i]->cbCertEncoded;
476 certBlob[i].pbData = pSignPara->rgpMsgCert[i]->pbCertEncoded;
478 signInfo.cCertEncoded = pSignPara->cMsgCert;
479 signInfo.rgCertEncoded = certBlob;
481 else
482 ret = FALSE;
484 if (pSignPara->cMsgCrl)
486 crlBlob = CryptMemAlloc(sizeof(CRL_BLOB) * pSignPara->cMsgCrl);
487 if (crlBlob)
489 for (i = 0; i < pSignPara->cMsgCrl; ++i)
491 crlBlob[i].cbData = pSignPara->rgpMsgCrl[i]->cbCrlEncoded;
492 crlBlob[i].pbData = pSignPara->rgpMsgCrl[i]->pbCrlEncoded;
494 signInfo.cCrlEncoded = pSignPara->cMsgCrl;
495 signInfo.rgCrlEncoded = crlBlob;
497 else
498 ret = FALSE;
500 if (pSignPara->dwFlags || pSignPara->dwInnerContentType)
501 FIXME("unimplemented feature\n");
503 if (ret)
504 msg = CryptMsgOpenToEncode(pSignPara->dwMsgEncodingType,
505 fDetachedSignature ? CMSG_DETACHED_FLAG : 0, CMSG_SIGNED, &signInfo,
506 NULL, NULL);
507 if (msg)
509 if (cToBeSigned)
511 for (i = 0; ret && i < cToBeSigned; ++i)
513 ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i],
514 i == cToBeSigned - 1 ? TRUE : FALSE);
517 else
518 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
519 if (ret)
520 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbSignedBlob,
521 pcbSignedBlob);
522 CryptMsgClose(msg);
524 else
525 ret = FALSE;
527 CryptMemFree(crlBlob);
528 CryptMemFree(certBlob);
529 if (freeProv)
530 CryptReleaseContext(hCryptProv, 0);
531 return ret;
534 BOOL WINAPI CryptEncryptMessage(PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
535 DWORD cRecipientCert, PCCERT_CONTEXT rgpRecipientCert[],
536 const BYTE *pbToBeEncrypted, DWORD cbToBeEncrypted, BYTE *pbEncryptedBlob,
537 DWORD *pcbEncryptedBlob)
539 BOOL ret = TRUE;
540 DWORD i;
541 PCERT_INFO *certInfo = NULL;
542 CMSG_ENVELOPED_ENCODE_INFO envelopedInfo;
543 HCRYPTMSG msg = 0;
545 TRACE("(%p, %d, %p, %p, %d, %p, %p)\n", pEncryptPara, cRecipientCert,
546 rgpRecipientCert, pbToBeEncrypted, cbToBeEncrypted, pbEncryptedBlob,
547 pcbEncryptedBlob);
549 if (pEncryptPara->cbSize != sizeof(CRYPT_ENCRYPT_MESSAGE_PARA) ||
550 GET_CMSG_ENCODING_TYPE(pEncryptPara->dwMsgEncodingType) !=
551 PKCS_7_ASN_ENCODING)
553 *pcbEncryptedBlob = 0;
554 SetLastError(E_INVALIDARG);
555 return FALSE;
558 memset(&envelopedInfo, 0, sizeof(envelopedInfo));
559 envelopedInfo.cbSize = sizeof(envelopedInfo);
560 envelopedInfo.hCryptProv = pEncryptPara->hCryptProv;
561 envelopedInfo.ContentEncryptionAlgorithm =
562 pEncryptPara->ContentEncryptionAlgorithm;
563 envelopedInfo.pvEncryptionAuxInfo = pEncryptPara->pvEncryptionAuxInfo;
565 if (cRecipientCert)
567 certInfo = CryptMemAlloc(sizeof(PCERT_INFO) * cRecipientCert);
568 if (certInfo)
570 for (i = 0; i < cRecipientCert; ++i)
571 certInfo[i] = rgpRecipientCert[i]->pCertInfo;
572 envelopedInfo.cRecipients = cRecipientCert;
573 envelopedInfo.rgpRecipientCert = certInfo;
575 else
576 ret = FALSE;
579 if (ret)
580 msg = CryptMsgOpenToEncode(pEncryptPara->dwMsgEncodingType, 0,
581 CMSG_ENVELOPED, &envelopedInfo, NULL, NULL);
582 if (msg)
584 ret = CryptMsgUpdate(msg, pbToBeEncrypted, cbToBeEncrypted, TRUE);
585 if (ret)
586 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbEncryptedBlob,
587 pcbEncryptedBlob);
588 CryptMsgClose(msg);
590 else
591 ret = FALSE;
593 CryptMemFree(certInfo);
594 if (!ret) *pcbEncryptedBlob = 0;
595 return ret;