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 && pcbDecoded) 214 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded, 215 pcbDecoded); 216 if (ret) 217 { 218 CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg, 219 dwSignerIndex); 220 221 ret = FALSE; 222 if (certInfo) 223 { 224 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG, 225 pVerifyPara->dwMsgAndCertEncodingType, 226 pVerifyPara->hCryptProv, 0, msg); 227 228 if (store) 229 { 230 PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate( 231 msg, pVerifyPara, certInfo, store); 232 233 if (cert) 234 { 235 ret = CryptMsgControl(msg, 0, 236 CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo); 237 if (ret && ppSignerCert) 238 *ppSignerCert = cert; 239 else 240 CertFreeCertificateContext(cert); 241 } 242 CertCloseStore(store, 0); 243 } 244 } 245 CryptMemFree(certInfo); 246 } 247 CryptMsgClose(msg); 248 } 249 if(!ret && pcbDecoded) 250 *pcbDecoded = 0; 251 TRACE("returning %d\n", ret); 252 return ret; 253 } 254 255 BOOL WINAPI CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara, 256 BOOL fDetachedHash, DWORD cToBeHashed, const BYTE *rgpbToBeHashed[], 257 DWORD rgcbToBeHashed[], BYTE *pbHashedBlob, DWORD *pcbHashedBlob, 258 BYTE *pbComputedHash, DWORD *pcbComputedHash) 259 { 260 DWORD i, flags; 261 BOOL ret = FALSE; 262 HCRYPTMSG msg; 263 CMSG_HASHED_ENCODE_INFO info; 264 265 TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara, fDetachedHash, 266 cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, pcbHashedBlob, 267 pbComputedHash, pcbComputedHash); 268 269 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA)) 270 { 271 SetLastError(E_INVALIDARG); 272 return FALSE; 273 } 274 /* Native seems to ignore any encoding type other than the expected 275 * PKCS_7_ASN_ENCODING 276 */ 277 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) != 278 PKCS_7_ASN_ENCODING) 279 return TRUE; 280 /* Native also seems to do nothing if the output parameter isn't given */ 281 if (!pcbHashedBlob) 282 return TRUE; 283 284 flags = fDetachedHash ? CMSG_DETACHED_FLAG : 0; 285 memset(&info, 0, sizeof(info)); 286 info.cbSize = sizeof(info); 287 info.hCryptProv = pHashPara->hCryptProv; 288 info.HashAlgorithm = pHashPara->HashAlgorithm; 289 info.pvHashAuxInfo = pHashPara->pvHashAuxInfo; 290 msg = CryptMsgOpenToEncode(pHashPara->dwMsgEncodingType, flags, CMSG_HASHED, 291 &info, NULL, NULL); 292 if (msg) 293 { 294 for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++) 295 ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i], i == cToBeHashed - 1); 296 if (ret) 297 { 298 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob, 299 pcbHashedBlob); 300 if (ret && pcbComputedHash) 301 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, 302 pbComputedHash, pcbComputedHash); 303 } 304 CryptMsgClose(msg); 305 } 306 return ret; 307 } 308 309 BOOL WINAPI CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara, 310 BYTE *pbDetachedHashBlob, DWORD cbDetachedHashBlob, DWORD cToBeHashed, 311 const BYTE *rgpbToBeHashed[], DWORD rgcbToBeHashed[], BYTE *pbComputedHash, 312 DWORD *pcbComputedHash) 313 { 314 HCRYPTMSG msg; 315 BOOL ret = FALSE; 316 317 TRACE("(%p, %p, %d, %d, %p, %p, %p, %p)\n", pHashPara, pbDetachedHashBlob, 318 cbDetachedHashBlob, cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, 319 pbComputedHash, pcbComputedHash); 320 321 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA)) 322 { 323 SetLastError(E_INVALIDARG); 324 return FALSE; 325 } 326 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) != 327 PKCS_7_ASN_ENCODING) 328 { 329 SetLastError(E_INVALIDARG); 330 return FALSE; 331 } 332 msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, CMSG_DETACHED_FLAG, 333 0, pHashPara->hCryptProv, NULL, NULL); 334 if (msg) 335 { 336 DWORD i; 337 338 ret = CryptMsgUpdate(msg, pbDetachedHashBlob, cbDetachedHashBlob, TRUE); 339 if (ret) 340 { 341 if (cToBeHashed) 342 { 343 for (i = 0; ret && i < cToBeHashed; i++) 344 { 345 ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], 346 rgcbToBeHashed[i], i == cToBeHashed - 1); 347 } 348 } 349 else 350 ret = CryptMsgUpdate(msg, NULL, 0, TRUE); 351 } 352 if (ret) 353 { 354 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL); 355 if (ret && pcbComputedHash) 356 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, 357 pbComputedHash, pcbComputedHash); 358 } 359 CryptMsgClose(msg); 360 } 361 return ret; 362 } 363 364 BOOL WINAPI CryptVerifyMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara, 365 BYTE *pbHashedBlob, DWORD cbHashedBlob, BYTE *pbToBeHashed, 366 DWORD *pcbToBeHashed, BYTE *pbComputedHash, DWORD *pcbComputedHash) 367 { 368 HCRYPTMSG msg; 369 BOOL ret = FALSE; 370 371 TRACE("(%p, %p, %d, %p, %p, %p, %p)\n", pHashPara, pbHashedBlob, 372 cbHashedBlob, pbToBeHashed, pcbToBeHashed, pbComputedHash, 373 pcbComputedHash); 374 375 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA)) 376 { 377 SetLastError(E_INVALIDARG); 378 return FALSE; 379 } 380 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) != 381 PKCS_7_ASN_ENCODING) 382 { 383 SetLastError(E_INVALIDARG); 384 return FALSE; 385 } 386 msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, 0, 0, 387 pHashPara->hCryptProv, NULL, NULL); 388 if (msg) 389 { 390 ret = CryptMsgUpdate(msg, pbHashedBlob, cbHashedBlob, TRUE); 391 if (ret) 392 { 393 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL); 394 if (ret && pcbToBeHashed) 395 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, 396 pbToBeHashed, pcbToBeHashed); 397 if (ret && pcbComputedHash) 398 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, 399 pbComputedHash, pcbComputedHash); 400 } 401 CryptMsgClose(msg); 402 } 403 return ret; 404 } 405 406 BOOL WINAPI CryptSignMessage(PCRYPT_SIGN_MESSAGE_PARA pSignPara, 407 BOOL fDetachedSignature, DWORD cToBeSigned, const BYTE *rgpbToBeSigned[], 408 DWORD rgcbToBeSigned[], BYTE *pbSignedBlob, DWORD *pcbSignedBlob) 409 { 410 HCRYPTPROV hCryptProv; 411 BOOL ret, freeProv = FALSE; 412 DWORD i, keySpec; 413 PCERT_BLOB certBlob = NULL; 414 PCRL_BLOB crlBlob = NULL; 415 CMSG_SIGNED_ENCODE_INFO signInfo; 416 CMSG_SIGNER_ENCODE_INFO signer; 417 HCRYPTMSG msg = 0; 418 419 TRACE("(%p, %d, %d, %p, %p, %p, %p)\n", pSignPara, fDetachedSignature, 420 cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, pbSignedBlob, pcbSignedBlob); 421 422 if (pSignPara->cbSize != sizeof(CRYPT_SIGN_MESSAGE_PARA) || 423 GET_CMSG_ENCODING_TYPE(pSignPara->dwMsgEncodingType) != 424 PKCS_7_ASN_ENCODING) 425 { 426 *pcbSignedBlob = 0; 427 SetLastError(E_INVALIDARG); 428 return FALSE; 429 } 430 if (!pSignPara->pSigningCert) 431 return TRUE; 432 433 ret = CryptAcquireCertificatePrivateKey(pSignPara->pSigningCert, 434 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hCryptProv, &keySpec, &freeProv); 435 if (!ret) 436 return FALSE; 437 438 memset(&signer, 0, sizeof(signer)); 439 signer.cbSize = sizeof(signer); 440 signer.pCertInfo = pSignPara->pSigningCert->pCertInfo; 441 signer.hCryptProv = hCryptProv; 442 signer.dwKeySpec = keySpec; 443 signer.HashAlgorithm = pSignPara->HashAlgorithm; 444 signer.pvHashAuxInfo = pSignPara->pvHashAuxInfo; 445 signer.cAuthAttr = pSignPara->cAuthAttr; 446 signer.rgAuthAttr = pSignPara->rgAuthAttr; 447 signer.cUnauthAttr = pSignPara->cUnauthAttr; 448 signer.rgUnauthAttr = pSignPara->rgUnauthAttr; 449 450 memset(&signInfo, 0, sizeof(signInfo)); 451 signInfo.cbSize = sizeof(signInfo); 452 signInfo.cSigners = 1; 453 signInfo.rgSigners = &signer; 454 455 if (pSignPara->cMsgCert) 456 { 457 certBlob = CryptMemAlloc(sizeof(CERT_BLOB) * pSignPara->cMsgCert); 458 if (certBlob) 459 { 460 for (i = 0; i < pSignPara->cMsgCert; ++i) 461 { 462 certBlob[i].cbData = pSignPara->rgpMsgCert[i]->cbCertEncoded; 463 certBlob[i].pbData = pSignPara->rgpMsgCert[i]->pbCertEncoded; 464 } 465 signInfo.cCertEncoded = pSignPara->cMsgCert; 466 signInfo.rgCertEncoded = certBlob; 467 } 468 else 469 ret = FALSE; 470 } 471 if (pSignPara->cMsgCrl) 472 { 473 crlBlob = CryptMemAlloc(sizeof(CRL_BLOB) * pSignPara->cMsgCrl); 474 if (crlBlob) 475 { 476 for (i = 0; i < pSignPara->cMsgCrl; ++i) 477 { 478 crlBlob[i].cbData = pSignPara->rgpMsgCrl[i]->cbCrlEncoded; 479 crlBlob[i].pbData = pSignPara->rgpMsgCrl[i]->pbCrlEncoded; 480 } 481 signInfo.cCrlEncoded = pSignPara->cMsgCrl; 482 signInfo.rgCrlEncoded = crlBlob; 483 } 484 else 485 ret = FALSE; 486 } 487 if (pSignPara->dwFlags || pSignPara->dwInnerContentType) 488 FIXME("unimplemented feature\n"); 489 490 if (ret) 491 msg = CryptMsgOpenToEncode(pSignPara->dwMsgEncodingType, 492 fDetachedSignature ? CMSG_DETACHED_FLAG : 0, CMSG_SIGNED, &signInfo, 493 NULL, NULL); 494 if (msg) 495 { 496 if (cToBeSigned) 497 { 498 for (i = 0; ret && i < cToBeSigned; ++i) 499 { 500 ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i], 501 i == cToBeSigned - 1); 502 } 503 } 504 else 505 ret = CryptMsgUpdate(msg, NULL, 0, TRUE); 506 if (ret) 507 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbSignedBlob, 508 pcbSignedBlob); 509 CryptMsgClose(msg); 510 } 511 else 512 ret = FALSE; 513 514 CryptMemFree(crlBlob); 515 CryptMemFree(certBlob); 516 if (freeProv) 517 CryptReleaseContext(hCryptProv, 0); 518 return ret; 519 } 520 521 BOOL WINAPI CryptEncryptMessage(PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara, 522 DWORD cRecipientCert, PCCERT_CONTEXT rgpRecipientCert[], 523 const BYTE *pbToBeEncrypted, DWORD cbToBeEncrypted, BYTE *pbEncryptedBlob, 524 DWORD *pcbEncryptedBlob) 525 { 526 BOOL ret = TRUE; 527 DWORD i; 528 PCERT_INFO *certInfo = NULL; 529 CMSG_ENVELOPED_ENCODE_INFO envelopedInfo; 530 HCRYPTMSG msg = 0; 531 532 TRACE("(%p, %d, %p, %p, %d, %p, %p)\n", pEncryptPara, cRecipientCert, 533 rgpRecipientCert, pbToBeEncrypted, cbToBeEncrypted, pbEncryptedBlob, 534 pcbEncryptedBlob); 535 536 if (pEncryptPara->cbSize != sizeof(CRYPT_ENCRYPT_MESSAGE_PARA) || 537 GET_CMSG_ENCODING_TYPE(pEncryptPara->dwMsgEncodingType) != 538 PKCS_7_ASN_ENCODING) 539 { 540 *pcbEncryptedBlob = 0; 541 SetLastError(E_INVALIDARG); 542 return FALSE; 543 } 544 545 memset(&envelopedInfo, 0, sizeof(envelopedInfo)); 546 envelopedInfo.cbSize = sizeof(envelopedInfo); 547 envelopedInfo.hCryptProv = pEncryptPara->hCryptProv; 548 envelopedInfo.ContentEncryptionAlgorithm = 549 pEncryptPara->ContentEncryptionAlgorithm; 550 envelopedInfo.pvEncryptionAuxInfo = pEncryptPara->pvEncryptionAuxInfo; 551 552 if (cRecipientCert) 553 { 554 certInfo = CryptMemAlloc(sizeof(PCERT_INFO) * cRecipientCert); 555 if (certInfo) 556 { 557 for (i = 0; i < cRecipientCert; ++i) 558 certInfo[i] = rgpRecipientCert[i]->pCertInfo; 559 envelopedInfo.cRecipients = cRecipientCert; 560 envelopedInfo.rgpRecipientCert = certInfo; 561 } 562 else 563 ret = FALSE; 564 } 565 566 if (ret) 567 msg = CryptMsgOpenToEncode(pEncryptPara->dwMsgEncodingType, 0, 568 CMSG_ENVELOPED, &envelopedInfo, NULL, NULL); 569 if (msg) 570 { 571 ret = CryptMsgUpdate(msg, pbToBeEncrypted, cbToBeEncrypted, TRUE); 572 if (ret) 573 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbEncryptedBlob, 574 pcbEncryptedBlob); 575 CryptMsgClose(msg); 576 } 577 else 578 ret = FALSE; 579 580 CryptMemFree(certInfo); 581 if (!ret) *pcbEncryptedBlob = 0; 582 return ret; 583 } 584