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 "config.h" 20 #include "wine/port.h" 21 22 #include <stdarg.h> 23 #define NONAMELESSUNION 24 #include "windef.h" 25 #include "winbase.h" 26 #include "wincrypt.h" 27 #include "snmp.h" 28 29 #include "wine/debug.h" 30 #include "wine/exception.h" 31 #include "crypt32_private.h" 32 33 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 34 35 /* Called when a message's ref count reaches zero. Free any message-specific 36 * data here. 37 */ 38 typedef void (*CryptMsgCloseFunc)(HCRYPTMSG msg); 39 40 typedef BOOL (*CryptMsgGetParamFunc)(HCRYPTMSG hCryptMsg, DWORD dwParamType, 41 DWORD dwIndex, void *pvData, DWORD *pcbData); 42 43 typedef BOOL (*CryptMsgUpdateFunc)(HCRYPTMSG hCryptMsg, const BYTE *pbData, 44 DWORD cbData, BOOL fFinal); 45 46 typedef BOOL (*CryptMsgControlFunc)(HCRYPTMSG hCryptMsg, DWORD dwFlags, 47 DWORD dwCtrlType, const void *pvCtrlPara); 48 49 static BOOL CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags, 50 DWORD dwCtrlType, const void *pvCtrlPara) 51 { 52 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara); 53 SetLastError(E_INVALIDARG); 54 return FALSE; 55 } 56 57 typedef enum _CryptMsgState { 58 MsgStateInit, 59 MsgStateUpdated, 60 MsgStateDataFinalized, 61 MsgStateFinalized 62 } CryptMsgState; 63 64 typedef struct _CryptMsgBase 65 { 66 LONG ref; 67 DWORD open_flags; 68 BOOL streamed; 69 CMSG_STREAM_INFO stream_info; 70 CryptMsgState state; 71 CryptMsgCloseFunc close; 72 CryptMsgUpdateFunc update; 73 CryptMsgGetParamFunc get_param; 74 CryptMsgControlFunc control; 75 } CryptMsgBase; 76 77 static inline void CryptMsgBase_Init(CryptMsgBase *msg, DWORD dwFlags, 78 PCMSG_STREAM_INFO pStreamInfo, CryptMsgCloseFunc close, 79 CryptMsgGetParamFunc get_param, CryptMsgUpdateFunc update, 80 CryptMsgControlFunc control) 81 { 82 msg->ref = 1; 83 msg->open_flags = dwFlags; 84 if (pStreamInfo) 85 { 86 msg->streamed = TRUE; 87 msg->stream_info = *pStreamInfo; 88 } 89 else 90 { 91 msg->streamed = FALSE; 92 memset(&msg->stream_info, 0, sizeof(msg->stream_info)); 93 } 94 msg->close = close; 95 msg->get_param = get_param; 96 msg->update = update; 97 msg->control = control; 98 msg->state = MsgStateInit; 99 } 100 101 typedef struct _CDataEncodeMsg 102 { 103 CryptMsgBase base; 104 DWORD bare_content_len; 105 LPBYTE bare_content; 106 } CDataEncodeMsg; 107 108 static const BYTE empty_data_content[] = { 0x04,0x00 }; 109 110 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg) 111 { 112 CDataEncodeMsg *msg = hCryptMsg; 113 114 if (msg->bare_content != empty_data_content) 115 LocalFree(msg->bare_content); 116 } 117 118 static BOOL WINAPI CRYPT_EncodeContentLength(DWORD dwCertEncodingType, 119 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 120 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 121 { 122 DWORD dataLen = *(DWORD *)pvStructInfo; 123 DWORD lenBytes; 124 BOOL ret = TRUE; 125 126 /* Trick: report bytes needed based on total message length, even though 127 * the message isn't available yet. The caller will use the length 128 * reported here to encode its length. 129 */ 130 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 131 if (!pbEncoded) 132 *pcbEncoded = 1 + lenBytes + dataLen; 133 else 134 { 135 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 136 pcbEncoded, 1 + lenBytes))) 137 { 138 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 139 pbEncoded = *(BYTE **)pbEncoded; 140 *pbEncoded++ = ASN_OCTETSTRING; 141 CRYPT_EncodeLen(dataLen, pbEncoded, 142 &lenBytes); 143 } 144 } 145 return ret; 146 } 147 148 static BOOL CRYPT_EncodeDataContentInfoHeader(const CDataEncodeMsg *msg, 149 CRYPT_DATA_BLOB *header) 150 { 151 BOOL ret; 152 153 if (msg->base.streamed && msg->base.stream_info.cbContent == 0xffffffff) 154 { 155 static const BYTE headerValue[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48, 156 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 }; 157 158 header->pbData = LocalAlloc(0, sizeof(headerValue)); 159 if (header->pbData) 160 { 161 header->cbData = sizeof(headerValue); 162 memcpy(header->pbData, headerValue, sizeof(headerValue)); 163 ret = TRUE; 164 } 165 else 166 ret = FALSE; 167 } 168 else 169 { 170 struct AsnConstructedItem constructed = { 0, 171 &msg->base.stream_info.cbContent, CRYPT_EncodeContentLength }; 172 struct AsnEncodeSequenceItem items[2] = { 173 { szOID_RSA_data, CRYPT_AsnEncodeOid, 0 }, 174 { &constructed, CRYPT_AsnEncodeConstructed, 0 }, 175 }; 176 177 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 178 sizeof(items) / sizeof(items[0]), CRYPT_ENCODE_ALLOC_FLAG, NULL, 179 (LPBYTE)&header->pbData, &header->cbData); 180 if (ret) 181 { 182 /* Trick: subtract the content length from the reported length, 183 * as the actual content hasn't come yet. 184 */ 185 header->cbData -= msg->base.stream_info.cbContent; 186 } 187 } 188 return ret; 189 } 190 191 static BOOL CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 192 DWORD cbData, BOOL fFinal) 193 { 194 CDataEncodeMsg *msg = hCryptMsg; 195 BOOL ret = FALSE; 196 197 if (msg->base.state == MsgStateFinalized) 198 SetLastError(CRYPT_E_MSG_ERROR); 199 else if (msg->base.streamed) 200 { 201 __TRY 202 { 203 if (msg->base.state != MsgStateUpdated) 204 { 205 CRYPT_DATA_BLOB header; 206 207 ret = CRYPT_EncodeDataContentInfoHeader(msg, &header); 208 if (ret) 209 { 210 ret = msg->base.stream_info.pfnStreamOutput( 211 msg->base.stream_info.pvArg, header.pbData, header.cbData, 212 FALSE); 213 LocalFree(header.pbData); 214 } 215 } 216 /* Curiously, every indefinite-length streamed update appears to 217 * get its own tag and length, regardless of fFinal. 218 */ 219 if (msg->base.stream_info.cbContent == 0xffffffff) 220 { 221 BYTE *header; 222 DWORD headerLen; 223 224 ret = CRYPT_EncodeContentLength(X509_ASN_ENCODING, NULL, 225 &cbData, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&header, 226 &headerLen); 227 if (ret) 228 { 229 ret = msg->base.stream_info.pfnStreamOutput( 230 msg->base.stream_info.pvArg, header, headerLen, 231 FALSE); 232 LocalFree(header); 233 } 234 } 235 if (!fFinal) 236 { 237 ret = msg->base.stream_info.pfnStreamOutput( 238 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData, 239 FALSE); 240 msg->base.state = MsgStateUpdated; 241 } 242 else 243 { 244 msg->base.state = MsgStateFinalized; 245 if (msg->base.stream_info.cbContent == 0xffffffff) 246 { 247 BYTE indefinite_trailer[6] = { 0 }; 248 249 ret = msg->base.stream_info.pfnStreamOutput( 250 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData, 251 FALSE); 252 if (ret) 253 ret = msg->base.stream_info.pfnStreamOutput( 254 msg->base.stream_info.pvArg, indefinite_trailer, 255 sizeof(indefinite_trailer), TRUE); 256 } 257 else 258 ret = msg->base.stream_info.pfnStreamOutput( 259 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData, TRUE); 260 } 261 } 262 __EXCEPT_PAGE_FAULT 263 { 264 SetLastError(STATUS_ACCESS_VIOLATION); 265 ret = FALSE; 266 } 267 __ENDTRY; 268 } 269 else 270 { 271 if (!fFinal) 272 { 273 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 274 SetLastError(E_INVALIDARG); 275 else 276 SetLastError(CRYPT_E_MSG_ERROR); 277 } 278 else 279 { 280 CRYPT_DATA_BLOB blob = { cbData, (LPBYTE)pbData }; 281 282 msg->base.state = MsgStateFinalized; 283 /* non-streamed data messages don't allow non-final updates, 284 * don't bother checking whether data already exist, they can't. 285 */ 286 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, 287 &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL, &msg->bare_content, 288 &msg->bare_content_len); 289 } 290 } 291 return ret; 292 } 293 294 static BOOL CRYPT_CopyParam(void *pvData, DWORD *pcbData, const void *src, 295 DWORD len) 296 { 297 BOOL ret = TRUE; 298 299 if (!pvData) 300 *pcbData = len; 301 else if (*pcbData < len) 302 { 303 *pcbData = len; 304 SetLastError(ERROR_MORE_DATA); 305 ret = FALSE; 306 } 307 else 308 { 309 *pcbData = len; 310 memcpy(pvData, src, len); 311 } 312 return ret; 313 } 314 315 static BOOL CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 316 DWORD dwIndex, void *pvData, DWORD *pcbData) 317 { 318 CDataEncodeMsg *msg = hCryptMsg; 319 BOOL ret = FALSE; 320 321 switch (dwParamType) 322 { 323 case CMSG_CONTENT_PARAM: 324 if (msg->base.streamed) 325 SetLastError(E_INVALIDARG); 326 else 327 { 328 CRYPT_CONTENT_INFO info; 329 char rsa_data[] = "1.2.840.113549.1.7.1"; 330 331 info.pszObjId = rsa_data; 332 info.Content.cbData = msg->bare_content_len; 333 info.Content.pbData = msg->bare_content; 334 ret = CryptEncodeObject(X509_ASN_ENCODING, PKCS_CONTENT_INFO, &info, 335 pvData, pcbData); 336 } 337 break; 338 case CMSG_BARE_CONTENT_PARAM: 339 if (msg->base.streamed) 340 SetLastError(E_INVALIDARG); 341 else 342 ret = CRYPT_CopyParam(pvData, pcbData, msg->bare_content, 343 msg->bare_content_len); 344 break; 345 default: 346 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 347 } 348 return ret; 349 } 350 351 static HCRYPTMSG CDataEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo, 352 LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo) 353 { 354 CDataEncodeMsg *msg; 355 356 if (pvMsgEncodeInfo) 357 { 358 SetLastError(E_INVALIDARG); 359 return NULL; 360 } 361 msg = CryptMemAlloc(sizeof(CDataEncodeMsg)); 362 if (msg) 363 { 364 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 365 CDataEncodeMsg_Close, CDataEncodeMsg_GetParam, CDataEncodeMsg_Update, 366 CRYPT_DefaultMsgControl); 367 msg->bare_content_len = sizeof(empty_data_content); 368 msg->bare_content = (LPBYTE)empty_data_content; 369 } 370 return msg; 371 } 372 373 typedef struct _CHashEncodeMsg 374 { 375 CryptMsgBase base; 376 HCRYPTPROV prov; 377 HCRYPTHASH hash; 378 CRYPT_DATA_BLOB data; 379 } CHashEncodeMsg; 380 381 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg) 382 { 383 CHashEncodeMsg *msg = hCryptMsg; 384 385 CryptMemFree(msg->data.pbData); 386 CryptDestroyHash(msg->hash); 387 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) 388 CryptReleaseContext(msg->prov, 0); 389 } 390 391 static BOOL CRYPT_EncodePKCSDigestedData(CHashEncodeMsg *msg, void *pvData, 392 DWORD *pcbData) 393 { 394 BOOL ret; 395 ALG_ID algID; 396 DWORD size = sizeof(algID); 397 398 ret = CryptGetHashParam(msg->hash, HP_ALGID, (BYTE *)&algID, &size, 0); 399 if (ret) 400 { 401 CRYPT_DIGESTED_DATA digestedData = { 0 }; 402 char oid_rsa_data[] = szOID_RSA_data; 403 404 digestedData.version = CMSG_HASHED_DATA_PKCS_1_5_VERSION; 405 digestedData.DigestAlgorithm.pszObjId = (LPSTR)CertAlgIdToOID(algID); 406 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */ 407 /* Quirk: OID is only encoded messages if an update has happened */ 408 if (msg->base.state != MsgStateInit) 409 digestedData.ContentInfo.pszObjId = oid_rsa_data; 410 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && msg->data.cbData) 411 { 412 ret = CRYPT_AsnEncodeOctets(0, NULL, &msg->data, 413 CRYPT_ENCODE_ALLOC_FLAG, NULL, 414 (LPBYTE)&digestedData.ContentInfo.Content.pbData, 415 &digestedData.ContentInfo.Content.cbData); 416 } 417 if (msg->base.state == MsgStateFinalized) 418 { 419 size = sizeof(DWORD); 420 ret = CryptGetHashParam(msg->hash, HP_HASHSIZE, 421 (LPBYTE)&digestedData.hash.cbData, &size, 0); 422 if (ret) 423 { 424 digestedData.hash.pbData = CryptMemAlloc( 425 digestedData.hash.cbData); 426 ret = CryptGetHashParam(msg->hash, HP_HASHVAL, 427 digestedData.hash.pbData, &digestedData.hash.cbData, 0); 428 } 429 } 430 if (ret) 431 ret = CRYPT_AsnEncodePKCSDigestedData(&digestedData, pvData, 432 pcbData); 433 CryptMemFree(digestedData.hash.pbData); 434 LocalFree(digestedData.ContentInfo.Content.pbData); 435 } 436 return ret; 437 } 438 439 static BOOL CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 440 DWORD dwIndex, void *pvData, DWORD *pcbData) 441 { 442 CHashEncodeMsg *msg = hCryptMsg; 443 BOOL ret = FALSE; 444 445 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex, 446 pvData, pcbData); 447 448 switch (dwParamType) 449 { 450 case CMSG_BARE_CONTENT_PARAM: 451 if (msg->base.streamed) 452 SetLastError(E_INVALIDARG); 453 else 454 ret = CRYPT_EncodePKCSDigestedData(msg, pvData, pcbData); 455 break; 456 case CMSG_CONTENT_PARAM: 457 { 458 CRYPT_CONTENT_INFO info; 459 460 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL, 461 &info.Content.cbData); 462 if (ret) 463 { 464 info.Content.pbData = CryptMemAlloc(info.Content.cbData); 465 if (info.Content.pbData) 466 { 467 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, 468 info.Content.pbData, &info.Content.cbData); 469 if (ret) 470 { 471 char oid_rsa_hashed[] = szOID_RSA_hashedData; 472 473 info.pszObjId = oid_rsa_hashed; 474 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, 475 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData); 476 } 477 CryptMemFree(info.Content.pbData); 478 } 479 else 480 ret = FALSE; 481 } 482 break; 483 } 484 case CMSG_COMPUTED_HASH_PARAM: 485 ret = CryptGetHashParam(msg->hash, HP_HASHVAL, pvData, pcbData, 0); 486 break; 487 case CMSG_VERSION_PARAM: 488 if (msg->base.state != MsgStateFinalized) 489 SetLastError(CRYPT_E_MSG_ERROR); 490 else 491 { 492 DWORD version = CMSG_HASHED_DATA_PKCS_1_5_VERSION; 493 494 /* Since the data are always encoded as octets, the version is 495 * always 0 (see rfc3852, section 7) 496 */ 497 ret = CRYPT_CopyParam(pvData, pcbData, &version, sizeof(version)); 498 } 499 break; 500 default: 501 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 502 } 503 return ret; 504 } 505 506 static BOOL CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 507 DWORD cbData, BOOL fFinal) 508 { 509 CHashEncodeMsg *msg = hCryptMsg; 510 BOOL ret = FALSE; 511 512 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal); 513 514 if (msg->base.state == MsgStateFinalized) 515 SetLastError(CRYPT_E_MSG_ERROR); 516 else if (msg->base.streamed || (msg->base.open_flags & CMSG_DETACHED_FLAG)) 517 { 518 /* Doesn't do much, as stream output is never called, and you 519 * can't get the content. 520 */ 521 ret = CryptHashData(msg->hash, pbData, cbData, 0); 522 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated; 523 } 524 else 525 { 526 if (!fFinal) 527 SetLastError(CRYPT_E_MSG_ERROR); 528 else 529 { 530 ret = CryptHashData(msg->hash, pbData, cbData, 0); 531 if (ret) 532 { 533 msg->data.pbData = CryptMemAlloc(cbData); 534 if (msg->data.pbData) 535 { 536 memcpy(msg->data.pbData + msg->data.cbData, pbData, cbData); 537 msg->data.cbData += cbData; 538 } 539 else 540 ret = FALSE; 541 } 542 msg->base.state = MsgStateFinalized; 543 } 544 } 545 return ret; 546 } 547 548 static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo, 549 LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo) 550 { 551 CHashEncodeMsg *msg; 552 const CMSG_HASHED_ENCODE_INFO *info = pvMsgEncodeInfo; 553 HCRYPTPROV prov; 554 ALG_ID algID; 555 556 if (info->cbSize != sizeof(CMSG_HASHED_ENCODE_INFO)) 557 { 558 SetLastError(E_INVALIDARG); 559 return NULL; 560 } 561 if (!(algID = CertOIDToAlgId(info->HashAlgorithm.pszObjId))) 562 { 563 SetLastError(CRYPT_E_UNKNOWN_ALGO); 564 return NULL; 565 } 566 if (info->hCryptProv) 567 prov = info->hCryptProv; 568 else 569 { 570 prov = CRYPT_GetDefaultProvider(); 571 dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; 572 } 573 msg = CryptMemAlloc(sizeof(CHashEncodeMsg)); 574 if (msg) 575 { 576 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 577 CHashEncodeMsg_Close, CHashEncodeMsg_GetParam, CHashEncodeMsg_Update, 578 CRYPT_DefaultMsgControl); 579 msg->prov = prov; 580 msg->data.cbData = 0; 581 msg->data.pbData = NULL; 582 if (!CryptCreateHash(prov, algID, 0, 0, &msg->hash)) 583 { 584 CryptMsgClose(msg); 585 msg = NULL; 586 } 587 } 588 return msg; 589 } 590 591 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS 592 { 593 DWORD cbSize; 594 PCERT_INFO pCertInfo; 595 HCRYPTPROV hCryptProv; 596 DWORD dwKeySpec; 597 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; 598 void *pvHashAuxInfo; 599 DWORD cAuthAttr; 600 PCRYPT_ATTRIBUTE rgAuthAttr; 601 DWORD cUnauthAttr; 602 PCRYPT_ATTRIBUTE rgUnauthAttr; 603 CERT_ID SignerId; 604 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; 605 void *pvHashEncryptionAuxInfo; 606 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS; 607 608 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS 609 { 610 DWORD cbSize; 611 DWORD cSigners; 612 CMSG_SIGNER_ENCODE_INFO_WITH_CMS *rgSigners; 613 DWORD cCertEncoded; 614 PCERT_BLOB rgCertEncoded; 615 DWORD cCrlEncoded; 616 PCRL_BLOB rgCrlEncoded; 617 DWORD cAttrCertEncoded; 618 PCERT_BLOB rgAttrCertEncoded; 619 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS; 620 621 static BOOL CRYPT_IsValidSigner(const CMSG_SIGNER_ENCODE_INFO_WITH_CMS *signer) 622 { 623 if (signer->cbSize != sizeof(CMSG_SIGNER_ENCODE_INFO) && 624 signer->cbSize != sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS)) 625 { 626 SetLastError(E_INVALIDARG); 627 return FALSE; 628 } 629 if (signer->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO)) 630 { 631 if (!signer->pCertInfo->SerialNumber.cbData) 632 { 633 SetLastError(E_INVALIDARG); 634 return FALSE; 635 } 636 if (!signer->pCertInfo->Issuer.cbData) 637 { 638 SetLastError(E_INVALIDARG); 639 return FALSE; 640 } 641 } 642 else if (signer->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS)) 643 { 644 switch (signer->SignerId.dwIdChoice) 645 { 646 case 0: 647 if (!signer->pCertInfo->SerialNumber.cbData) 648 { 649 SetLastError(E_INVALIDARG); 650 return FALSE; 651 } 652 if (!signer->pCertInfo->Issuer.cbData) 653 { 654 SetLastError(E_INVALIDARG); 655 return FALSE; 656 } 657 break; 658 case CERT_ID_ISSUER_SERIAL_NUMBER: 659 if (!signer->SignerId.u.IssuerSerialNumber.SerialNumber.cbData) 660 { 661 SetLastError(E_INVALIDARG); 662 return FALSE; 663 } 664 if (!signer->SignerId.u.IssuerSerialNumber.Issuer.cbData) 665 { 666 SetLastError(E_INVALIDARG); 667 return FALSE; 668 } 669 break; 670 case CERT_ID_KEY_IDENTIFIER: 671 if (!signer->SignerId.u.KeyId.cbData) 672 { 673 SetLastError(E_INVALIDARG); 674 return FALSE; 675 } 676 break; 677 default: 678 SetLastError(E_INVALIDARG); 679 } 680 if (signer->HashEncryptionAlgorithm.pszObjId) 681 { 682 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n"); 683 return FALSE; 684 } 685 } 686 if (!signer->hCryptProv) 687 { 688 SetLastError(E_INVALIDARG); 689 return FALSE; 690 } 691 if (!CertOIDToAlgId(signer->HashAlgorithm.pszObjId)) 692 { 693 SetLastError(CRYPT_E_UNKNOWN_ALGO); 694 return FALSE; 695 } 696 return TRUE; 697 } 698 699 static BOOL CRYPT_ConstructBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in) 700 { 701 BOOL ret = TRUE; 702 703 out->cbData = in->cbData; 704 if (out->cbData) 705 { 706 out->pbData = CryptMemAlloc(out->cbData); 707 if (out->pbData) 708 memcpy(out->pbData, in->pbData, out->cbData); 709 else 710 ret = FALSE; 711 } 712 else 713 out->pbData = NULL; 714 return ret; 715 } 716 717 static BOOL CRYPT_ConstructBlobArray(DWORD *outCBlobs, 718 PCRYPT_DATA_BLOB *outPBlobs, DWORD cBlobs, const CRYPT_DATA_BLOB *pBlobs) 719 { 720 BOOL ret = TRUE; 721 722 *outCBlobs = cBlobs; 723 if (cBlobs) 724 { 725 *outPBlobs = CryptMemAlloc(cBlobs * sizeof(CRYPT_DATA_BLOB)); 726 if (*outPBlobs) 727 { 728 DWORD i; 729 730 memset(*outPBlobs, 0, cBlobs * sizeof(CRYPT_DATA_BLOB)); 731 for (i = 0; ret && i < cBlobs; i++) 732 ret = CRYPT_ConstructBlob(&(*outPBlobs)[i], &pBlobs[i]); 733 } 734 else 735 ret = FALSE; 736 } 737 return ret; 738 } 739 740 static void CRYPT_FreeBlobArray(DWORD cBlobs, PCRYPT_DATA_BLOB blobs) 741 { 742 DWORD i; 743 744 for (i = 0; i < cBlobs; i++) 745 CryptMemFree(blobs[i].pbData); 746 CryptMemFree(blobs); 747 } 748 749 static BOOL CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE *out, 750 const CRYPT_ATTRIBUTE *in) 751 { 752 BOOL ret; 753 754 out->pszObjId = CryptMemAlloc(strlen(in->pszObjId) + 1); 755 if (out->pszObjId) 756 { 757 strcpy(out->pszObjId, in->pszObjId); 758 ret = CRYPT_ConstructBlobArray(&out->cValue, &out->rgValue, 759 in->cValue, in->rgValue); 760 } 761 else 762 ret = FALSE; 763 return ret; 764 } 765 766 static BOOL CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES *out, 767 const CRYPT_ATTRIBUTES *in) 768 { 769 BOOL ret = TRUE; 770 771 out->cAttr = in->cAttr; 772 if (out->cAttr) 773 { 774 out->rgAttr = CryptMemAlloc(out->cAttr * sizeof(CRYPT_ATTRIBUTE)); 775 if (out->rgAttr) 776 { 777 DWORD i; 778 779 memset(out->rgAttr, 0, out->cAttr * sizeof(CRYPT_ATTRIBUTE)); 780 for (i = 0; ret && i < out->cAttr; i++) 781 ret = CRYPT_ConstructAttribute(&out->rgAttr[i], &in->rgAttr[i]); 782 } 783 else 784 ret = FALSE; 785 } 786 else 787 out->rgAttr = NULL; 788 return ret; 789 } 790 791 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */ 792 static BOOL CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO *info, 793 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS *in) 794 { 795 BOOL ret; 796 797 if (in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO)) 798 { 799 info->dwVersion = CMSG_SIGNER_INFO_V1; 800 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer, 801 &in->pCertInfo->Issuer); 802 if (ret) 803 ret = CRYPT_ConstructBlob( 804 &info->SignerId.u.IssuerSerialNumber.SerialNumber, 805 &in->pCertInfo->SerialNumber); 806 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 807 info->HashEncryptionAlgorithm.pszObjId = 808 in->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId; 809 if (ret) 810 ret = CRYPT_ConstructBlob(&info->HashEncryptionAlgorithm.Parameters, 811 &in->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters); 812 } 813 else 814 { 815 const CRYPT_ALGORITHM_IDENTIFIER *pEncrAlg; 816 817 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS). 818 * See CRYPT_IsValidSigner. 819 */ 820 if (!in->SignerId.dwIdChoice) 821 { 822 info->dwVersion = CMSG_SIGNER_INFO_V1; 823 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer, 824 &in->pCertInfo->Issuer); 825 if (ret) 826 ret = CRYPT_ConstructBlob( 827 &info->SignerId.u.IssuerSerialNumber.SerialNumber, 828 &in->pCertInfo->SerialNumber); 829 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 830 } 831 else if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 832 { 833 info->dwVersion = CMSG_SIGNER_INFO_V1; 834 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 835 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer, 836 &in->SignerId.u.IssuerSerialNumber.Issuer); 837 if (ret) 838 ret = CRYPT_ConstructBlob( 839 &info->SignerId.u.IssuerSerialNumber.SerialNumber, 840 &in->SignerId.u.IssuerSerialNumber.SerialNumber); 841 } 842 else 843 { 844 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */ 845 info->dwVersion = CMSG_SIGNER_INFO_V3; 846 info->SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER; 847 ret = CRYPT_ConstructBlob(&info->SignerId.u.KeyId, 848 &in->SignerId.u.KeyId); 849 } 850 pEncrAlg = in->HashEncryptionAlgorithm.pszObjId ? 851 &in->HashEncryptionAlgorithm : 852 &in->pCertInfo->SubjectPublicKeyInfo.Algorithm; 853 info->HashEncryptionAlgorithm.pszObjId = pEncrAlg->pszObjId; 854 if (ret) 855 ret = CRYPT_ConstructBlob(&info->HashEncryptionAlgorithm.Parameters, 856 &pEncrAlg->Parameters); 857 } 858 /* Assumption: algorithm IDs will point to static strings, not 859 * stack-based ones, so copying the pointer values is safe. 860 */ 861 info->HashAlgorithm.pszObjId = in->HashAlgorithm.pszObjId; 862 if (ret) 863 ret = CRYPT_ConstructBlob(&info->HashAlgorithm.Parameters, 864 &in->HashAlgorithm.Parameters); 865 if (ret) 866 ret = CRYPT_ConstructAttributes(&info->AuthAttrs, 867 (CRYPT_ATTRIBUTES *)&in->cAuthAttr); 868 if (ret) 869 ret = CRYPT_ConstructAttributes(&info->UnauthAttrs, 870 (CRYPT_ATTRIBUTES *)&in->cUnauthAttr); 871 return ret; 872 } 873 874 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO *info) 875 { 876 DWORD i, j; 877 878 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 879 { 880 CryptMemFree(info->SignerId.u.IssuerSerialNumber.Issuer.pbData); 881 CryptMemFree(info->SignerId.u.IssuerSerialNumber.SerialNumber.pbData); 882 } 883 else 884 CryptMemFree(info->SignerId.u.KeyId.pbData); 885 CryptMemFree(info->HashAlgorithm.Parameters.pbData); 886 CryptMemFree(info->HashEncryptionAlgorithm.Parameters.pbData); 887 CryptMemFree(info->EncryptedHash.pbData); 888 for (i = 0; i < info->AuthAttrs.cAttr; i++) 889 { 890 for (j = 0; j < info->AuthAttrs.rgAttr[i].cValue; j++) 891 CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue[j].pbData); 892 CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue); 893 CryptMemFree(info->AuthAttrs.rgAttr[i].pszObjId); 894 } 895 CryptMemFree(info->AuthAttrs.rgAttr); 896 for (i = 0; i < info->UnauthAttrs.cAttr; i++) 897 { 898 for (j = 0; j < info->UnauthAttrs.rgAttr[i].cValue; j++) 899 CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue[j].pbData); 900 CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue); 901 CryptMemFree(info->UnauthAttrs.rgAttr[i].pszObjId); 902 } 903 CryptMemFree(info->UnauthAttrs.rgAttr); 904 } 905 906 typedef struct _CSignerHandles 907 { 908 HCRYPTHASH contentHash; 909 HCRYPTHASH authAttrHash; 910 } CSignerHandles; 911 912 typedef struct _CSignedMsgData 913 { 914 CRYPT_SIGNED_INFO *info; 915 DWORD cSignerHandle; 916 CSignerHandles *signerHandles; 917 } CSignedMsgData; 918 919 /* Constructs the signer handles for the signerIndex'th signer of msg_data. 920 * Assumes signerIndex is a valid idnex, and that msg_data's info has already 921 * been constructed. 922 */ 923 static BOOL CSignedMsgData_ConstructSignerHandles(CSignedMsgData *msg_data, 924 DWORD signerIndex, HCRYPTPROV crypt_prov) 925 { 926 ALG_ID algID; 927 BOOL ret; 928 929 algID = CertOIDToAlgId( 930 msg_data->info->rgSignerInfo[signerIndex].HashAlgorithm.pszObjId); 931 ret = CryptCreateHash(crypt_prov, algID, 0, 0, 932 &msg_data->signerHandles->contentHash); 933 if (ret && msg_data->info->rgSignerInfo[signerIndex].AuthAttrs.cAttr > 0) 934 ret = CryptCreateHash(crypt_prov, algID, 0, 0, 935 &msg_data->signerHandles->authAttrHash); 936 return ret; 937 } 938 939 /* Allocates a CSignedMsgData's handles. Assumes its info has already been 940 * constructed. 941 */ 942 static BOOL CSignedMsgData_AllocateHandles(CSignedMsgData *msg_data) 943 { 944 BOOL ret = TRUE; 945 946 if (msg_data->info->cSignerInfo) 947 { 948 msg_data->signerHandles = 949 CryptMemAlloc(msg_data->info->cSignerInfo * sizeof(CSignerHandles)); 950 if (msg_data->signerHandles) 951 { 952 msg_data->cSignerHandle = msg_data->info->cSignerInfo; 953 memset(msg_data->signerHandles, 0, 954 msg_data->info->cSignerInfo * sizeof(CSignerHandles)); 955 } 956 else 957 { 958 msg_data->cSignerHandle = 0; 959 ret = FALSE; 960 } 961 } 962 else 963 { 964 msg_data->cSignerHandle = 0; 965 msg_data->signerHandles = NULL; 966 } 967 return ret; 968 } 969 970 static void CSignedMsgData_CloseHandles(CSignedMsgData *msg_data) 971 { 972 DWORD i; 973 974 for (i = 0; i < msg_data->cSignerHandle; i++) 975 { 976 if (msg_data->signerHandles[i].contentHash) 977 CryptDestroyHash(msg_data->signerHandles[i].contentHash); 978 if (msg_data->signerHandles[i].authAttrHash) 979 CryptDestroyHash(msg_data->signerHandles[i].authAttrHash); 980 } 981 CryptMemFree(msg_data->signerHandles); 982 msg_data->signerHandles = NULL; 983 msg_data->cSignerHandle = 0; 984 } 985 986 static BOOL CSignedMsgData_UpdateHash(CSignedMsgData *msg_data, 987 const BYTE *pbData, DWORD cbData) 988 { 989 DWORD i; 990 BOOL ret = TRUE; 991 992 for (i = 0; ret && i < msg_data->cSignerHandle; i++) 993 ret = CryptHashData(msg_data->signerHandles[i].contentHash, pbData, 994 cbData, 0); 995 return ret; 996 } 997 998 static BOOL CRYPT_AppendAttribute(CRYPT_ATTRIBUTES *out, 999 const CRYPT_ATTRIBUTE *in) 1000 { 1001 BOOL ret = FALSE; 1002 1003 out->rgAttr = CryptMemRealloc(out->rgAttr, 1004 (out->cAttr + 1) * sizeof(CRYPT_ATTRIBUTE)); 1005 if (out->rgAttr) 1006 { 1007 ret = CRYPT_ConstructAttribute(&out->rgAttr[out->cAttr], in); 1008 if (ret) 1009 out->cAttr++; 1010 } 1011 return ret; 1012 } 1013 1014 static BOOL CSignedMsgData_AppendMessageDigestAttribute( 1015 CSignedMsgData *msg_data, DWORD signerIndex) 1016 { 1017 BOOL ret; 1018 DWORD size; 1019 CRYPT_HASH_BLOB hash = { 0, NULL }, encodedHash = { 0, NULL }; 1020 char messageDigest[] = szOID_RSA_messageDigest; 1021 CRYPT_ATTRIBUTE messageDigestAttr = { messageDigest, 1, &encodedHash }; 1022 1023 size = sizeof(DWORD); 1024 ret = CryptGetHashParam( 1025 msg_data->signerHandles[signerIndex].contentHash, HP_HASHSIZE, 1026 (LPBYTE)&hash.cbData, &size, 0); 1027 if (ret) 1028 { 1029 hash.pbData = CryptMemAlloc(hash.cbData); 1030 ret = CryptGetHashParam( 1031 msg_data->signerHandles[signerIndex].contentHash, HP_HASHVAL, 1032 hash.pbData, &hash.cbData, 0); 1033 if (ret) 1034 { 1035 ret = CRYPT_AsnEncodeOctets(0, NULL, &hash, CRYPT_ENCODE_ALLOC_FLAG, 1036 NULL, (LPBYTE)&encodedHash.pbData, &encodedHash.cbData); 1037 if (ret) 1038 { 1039 ret = CRYPT_AppendAttribute( 1040 &msg_data->info->rgSignerInfo[signerIndex].AuthAttrs, 1041 &messageDigestAttr); 1042 LocalFree(encodedHash.pbData); 1043 } 1044 } 1045 CryptMemFree(hash.pbData); 1046 } 1047 return ret; 1048 } 1049 1050 typedef enum { 1051 Sign, 1052 Verify 1053 } SignOrVerify; 1054 1055 static BOOL CSignedMsgData_UpdateAuthenticatedAttributes( 1056 CSignedMsgData *msg_data, SignOrVerify flag) 1057 { 1058 DWORD i; 1059 BOOL ret = TRUE; 1060 1061 TRACE("(%p)\n", msg_data); 1062 1063 for (i = 0; ret && i < msg_data->info->cSignerInfo; i++) 1064 { 1065 if (msg_data->info->rgSignerInfo[i].AuthAttrs.cAttr) 1066 { 1067 if (flag == Sign) 1068 { 1069 BYTE oid_rsa_data_encoded[] = { 0x06,0x09,0x2a,0x86,0x48,0x86, 1070 0xf7,0x0d,0x01,0x07,0x01 }; 1071 CRYPT_DATA_BLOB content = { sizeof(oid_rsa_data_encoded), 1072 oid_rsa_data_encoded }; 1073 char contentType[] = szOID_RSA_contentType; 1074 CRYPT_ATTRIBUTE contentTypeAttr = { contentType, 1, &content }; 1075 1076 /* FIXME: does this depend on inner OID? */ 1077 ret = CRYPT_AppendAttribute( 1078 &msg_data->info->rgSignerInfo[i].AuthAttrs, &contentTypeAttr); 1079 if (ret) 1080 ret = CSignedMsgData_AppendMessageDigestAttribute(msg_data, 1081 i); 1082 } 1083 if (ret) 1084 { 1085 LPBYTE encodedAttrs; 1086 DWORD size; 1087 1088 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, PKCS_ATTRIBUTES, 1089 &msg_data->info->rgSignerInfo[i].AuthAttrs, 1090 CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedAttrs, &size); 1091 if (ret) 1092 { 1093 ret = CryptHashData( 1094 msg_data->signerHandles[i].authAttrHash, encodedAttrs, 1095 size, 0); 1096 LocalFree(encodedAttrs); 1097 } 1098 } 1099 } 1100 } 1101 TRACE("returning %d\n", ret); 1102 return ret; 1103 } 1104 1105 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB *hash) 1106 { 1107 DWORD i; 1108 BYTE tmp; 1109 1110 for (i = 0; i < hash->cbData / 2; i++) 1111 { 1112 tmp = hash->pbData[hash->cbData - i - 1]; 1113 hash->pbData[hash->cbData - i - 1] = hash->pbData[i]; 1114 hash->pbData[i] = tmp; 1115 } 1116 } 1117 1118 static BOOL CSignedMsgData_Sign(CSignedMsgData *msg_data) 1119 { 1120 DWORD i; 1121 BOOL ret = TRUE; 1122 1123 TRACE("(%p)\n", msg_data); 1124 1125 for (i = 0; ret && i < msg_data->info->cSignerInfo; i++) 1126 { 1127 HCRYPTHASH hash; 1128 1129 if (msg_data->info->rgSignerInfo[i].AuthAttrs.cAttr) 1130 hash = msg_data->signerHandles[i].authAttrHash; 1131 else 1132 hash = msg_data->signerHandles[i].contentHash; 1133 ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0, NULL, 1134 &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData); 1135 if (ret) 1136 { 1137 msg_data->info->rgSignerInfo[i].EncryptedHash.pbData = 1138 CryptMemAlloc( 1139 msg_data->info->rgSignerInfo[i].EncryptedHash.cbData); 1140 if (msg_data->info->rgSignerInfo[i].EncryptedHash.pbData) 1141 { 1142 ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0, 1143 msg_data->info->rgSignerInfo[i].EncryptedHash.pbData, 1144 &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData); 1145 if (ret) 1146 CRYPT_ReverseBytes( 1147 &msg_data->info->rgSignerInfo[i].EncryptedHash); 1148 } 1149 else 1150 ret = FALSE; 1151 } 1152 } 1153 return ret; 1154 } 1155 1156 static BOOL CSignedMsgData_Update(CSignedMsgData *msg_data, 1157 const BYTE *pbData, DWORD cbData, BOOL fFinal, SignOrVerify flag) 1158 { 1159 BOOL ret = CSignedMsgData_UpdateHash(msg_data, pbData, cbData); 1160 1161 if (ret && fFinal) 1162 { 1163 ret = CSignedMsgData_UpdateAuthenticatedAttributes(msg_data, flag); 1164 if (ret && flag == Sign) 1165 ret = CSignedMsgData_Sign(msg_data); 1166 } 1167 return ret; 1168 } 1169 1170 typedef struct _CSignedEncodeMsg 1171 { 1172 CryptMsgBase base; 1173 LPSTR innerOID; 1174 CRYPT_DATA_BLOB data; 1175 CSignedMsgData msg_data; 1176 } CSignedEncodeMsg; 1177 1178 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg) 1179 { 1180 CSignedEncodeMsg *msg = hCryptMsg; 1181 DWORD i; 1182 1183 CryptMemFree(msg->innerOID); 1184 CryptMemFree(msg->data.pbData); 1185 CRYPT_FreeBlobArray(msg->msg_data.info->cCertEncoded, 1186 msg->msg_data.info->rgCertEncoded); 1187 CRYPT_FreeBlobArray(msg->msg_data.info->cCrlEncoded, 1188 msg->msg_data.info->rgCrlEncoded); 1189 for (i = 0; i < msg->msg_data.info->cSignerInfo; i++) 1190 CSignerInfo_Free(&msg->msg_data.info->rgSignerInfo[i]); 1191 CSignedMsgData_CloseHandles(&msg->msg_data); 1192 CryptMemFree(msg->msg_data.info->rgSignerInfo); 1193 CryptMemFree(msg->msg_data.info); 1194 } 1195 1196 static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 1197 DWORD dwIndex, void *pvData, DWORD *pcbData) 1198 { 1199 CSignedEncodeMsg *msg = hCryptMsg; 1200 BOOL ret = FALSE; 1201 1202 switch (dwParamType) 1203 { 1204 case CMSG_CONTENT_PARAM: 1205 { 1206 CRYPT_CONTENT_INFO info; 1207 1208 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL, 1209 &info.Content.cbData); 1210 if (ret) 1211 { 1212 info.Content.pbData = CryptMemAlloc(info.Content.cbData); 1213 if (info.Content.pbData) 1214 { 1215 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, 1216 info.Content.pbData, &info.Content.cbData); 1217 if (ret) 1218 { 1219 char oid_rsa_signed[] = szOID_RSA_signedData; 1220 1221 info.pszObjId = oid_rsa_signed; 1222 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, 1223 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData); 1224 } 1225 CryptMemFree(info.Content.pbData); 1226 } 1227 else 1228 ret = FALSE; 1229 } 1230 break; 1231 } 1232 case CMSG_BARE_CONTENT_PARAM: 1233 { 1234 CRYPT_SIGNED_INFO info; 1235 BOOL freeContent = FALSE; 1236 1237 info = *msg->msg_data.info; 1238 if (!msg->innerOID || !strcmp(msg->innerOID, szOID_RSA_data)) 1239 { 1240 char oid_rsa_data[] = szOID_RSA_data; 1241 1242 /* Quirk: OID is only encoded messages if an update has happened */ 1243 if (msg->base.state != MsgStateInit) 1244 info.content.pszObjId = oid_rsa_data; 1245 else 1246 info.content.pszObjId = NULL; 1247 if (msg->data.cbData) 1248 { 1249 CRYPT_DATA_BLOB blob = { msg->data.cbData, msg->data.pbData }; 1250 1251 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, 1252 &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL, 1253 &info.content.Content.pbData, &info.content.Content.cbData); 1254 freeContent = TRUE; 1255 } 1256 else 1257 { 1258 info.content.Content.cbData = 0; 1259 info.content.Content.pbData = NULL; 1260 ret = TRUE; 1261 } 1262 } 1263 else 1264 { 1265 info.content.pszObjId = msg->innerOID; 1266 info.content.Content.cbData = msg->data.cbData; 1267 info.content.Content.pbData = msg->data.pbData; 1268 ret = TRUE; 1269 } 1270 if (ret) 1271 { 1272 ret = CRYPT_AsnEncodeCMSSignedInfo(&info, pvData, pcbData); 1273 if (freeContent) 1274 LocalFree(info.content.Content.pbData); 1275 } 1276 break; 1277 } 1278 case CMSG_COMPUTED_HASH_PARAM: 1279 if (dwIndex >= msg->msg_data.cSignerHandle) 1280 SetLastError(CRYPT_E_INVALID_INDEX); 1281 else 1282 ret = CryptGetHashParam( 1283 msg->msg_data.signerHandles[dwIndex].contentHash, HP_HASHVAL, 1284 pvData, pcbData, 0); 1285 break; 1286 case CMSG_ENCODED_SIGNER: 1287 if (dwIndex >= msg->msg_data.info->cSignerInfo) 1288 SetLastError(CRYPT_E_INVALID_INDEX); 1289 else 1290 ret = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 1291 CMS_SIGNER_INFO, &msg->msg_data.info->rgSignerInfo[dwIndex], 0, 1292 NULL, pvData, pcbData); 1293 break; 1294 case CMSG_VERSION_PARAM: 1295 ret = CRYPT_CopyParam(pvData, pcbData, &msg->msg_data.info->version, 1296 sizeof(msg->msg_data.info->version)); 1297 break; 1298 default: 1299 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 1300 } 1301 return ret; 1302 } 1303 1304 static BOOL CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 1305 DWORD cbData, BOOL fFinal) 1306 { 1307 CSignedEncodeMsg *msg = hCryptMsg; 1308 BOOL ret = FALSE; 1309 1310 if (msg->base.state == MsgStateFinalized) 1311 SetLastError(CRYPT_E_MSG_ERROR); 1312 else if (msg->base.streamed || (msg->base.open_flags & CMSG_DETACHED_FLAG)) 1313 { 1314 ret = CSignedMsgData_Update(&msg->msg_data, pbData, cbData, fFinal, 1315 Sign); 1316 if (msg->base.streamed) 1317 FIXME("streamed partial stub\n"); 1318 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated; 1319 } 1320 else 1321 { 1322 if (!fFinal) 1323 SetLastError(CRYPT_E_MSG_ERROR); 1324 else 1325 { 1326 if (cbData) 1327 { 1328 msg->data.pbData = CryptMemAlloc(cbData); 1329 if (msg->data.pbData) 1330 { 1331 memcpy(msg->data.pbData, pbData, cbData); 1332 msg->data.cbData = cbData; 1333 ret = TRUE; 1334 } 1335 } 1336 else 1337 ret = TRUE; 1338 if (ret) 1339 ret = CSignedMsgData_Update(&msg->msg_data, pbData, cbData, 1340 fFinal, Sign); 1341 msg->base.state = MsgStateFinalized; 1342 } 1343 } 1344 return ret; 1345 } 1346 1347 static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags, 1348 const void *pvMsgEncodeInfo, LPCSTR pszInnerContentObjID, 1349 PCMSG_STREAM_INFO pStreamInfo) 1350 { 1351 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS *info = pvMsgEncodeInfo; 1352 DWORD i; 1353 CSignedEncodeMsg *msg; 1354 1355 if (info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO) && 1356 info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS)) 1357 { 1358 SetLastError(E_INVALIDARG); 1359 return NULL; 1360 } 1361 if (info->cbSize == sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS) && 1362 info->cAttrCertEncoded) 1363 { 1364 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n"); 1365 return NULL; 1366 } 1367 for (i = 0; i < info->cSigners; i++) 1368 if (!CRYPT_IsValidSigner(&info->rgSigners[i])) 1369 return NULL; 1370 msg = CryptMemAlloc(sizeof(CSignedEncodeMsg)); 1371 if (msg) 1372 { 1373 BOOL ret = TRUE; 1374 1375 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 1376 CSignedEncodeMsg_Close, CSignedEncodeMsg_GetParam, 1377 CSignedEncodeMsg_Update, CRYPT_DefaultMsgControl); 1378 if (pszInnerContentObjID) 1379 { 1380 msg->innerOID = CryptMemAlloc(strlen(pszInnerContentObjID) + 1); 1381 if (msg->innerOID) 1382 strcpy(msg->innerOID, pszInnerContentObjID); 1383 else 1384 ret = FALSE; 1385 } 1386 else 1387 msg->innerOID = NULL; 1388 msg->data.cbData = 0; 1389 msg->data.pbData = NULL; 1390 if (ret) 1391 msg->msg_data.info = CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO)); 1392 else 1393 msg->msg_data.info = NULL; 1394 if (msg->msg_data.info) 1395 { 1396 memset(msg->msg_data.info, 0, sizeof(CRYPT_SIGNED_INFO)); 1397 msg->msg_data.info->version = CMSG_SIGNED_DATA_V1; 1398 } 1399 else 1400 ret = FALSE; 1401 if (ret) 1402 { 1403 if (info->cSigners) 1404 { 1405 msg->msg_data.info->rgSignerInfo = 1406 CryptMemAlloc(info->cSigners * sizeof(CMSG_CMS_SIGNER_INFO)); 1407 if (msg->msg_data.info->rgSignerInfo) 1408 { 1409 msg->msg_data.info->cSignerInfo = info->cSigners; 1410 memset(msg->msg_data.info->rgSignerInfo, 0, 1411 msg->msg_data.info->cSignerInfo * 1412 sizeof(CMSG_CMS_SIGNER_INFO)); 1413 ret = CSignedMsgData_AllocateHandles(&msg->msg_data); 1414 for (i = 0; ret && i < msg->msg_data.info->cSignerInfo; i++) 1415 { 1416 if (info->rgSigners[i].SignerId.dwIdChoice == 1417 CERT_ID_KEY_IDENTIFIER) 1418 msg->msg_data.info->version = CMSG_SIGNED_DATA_V3; 1419 ret = CSignerInfo_Construct( 1420 &msg->msg_data.info->rgSignerInfo[i], 1421 &info->rgSigners[i]); 1422 if (ret) 1423 { 1424 ret = CSignedMsgData_ConstructSignerHandles( 1425 &msg->msg_data, i, info->rgSigners[i].hCryptProv); 1426 if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) 1427 CryptReleaseContext(info->rgSigners[i].hCryptProv, 1428 0); 1429 } 1430 } 1431 } 1432 else 1433 ret = FALSE; 1434 } 1435 else 1436 { 1437 msg->msg_data.info->cSignerInfo = 0; 1438 msg->msg_data.signerHandles = NULL; 1439 msg->msg_data.cSignerHandle = 0; 1440 } 1441 } 1442 if (ret) 1443 ret = CRYPT_ConstructBlobArray(&msg->msg_data.info->cCertEncoded, 1444 &msg->msg_data.info->rgCertEncoded, info->cCertEncoded, 1445 info->rgCertEncoded); 1446 if (ret) 1447 ret = CRYPT_ConstructBlobArray(&msg->msg_data.info->cCrlEncoded, 1448 &msg->msg_data.info->rgCrlEncoded, info->cCrlEncoded, 1449 info->rgCrlEncoded); 1450 if (!ret) 1451 { 1452 CSignedEncodeMsg_Close(msg); 1453 CryptMemFree(msg); 1454 msg = NULL; 1455 } 1456 } 1457 return msg; 1458 } 1459 1460 typedef struct _CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS 1461 { 1462 DWORD cbSize; 1463 HCRYPTPROV_LEGACY hCryptProv; 1464 CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm; 1465 void *pvEncryptionAuxInfo; 1466 DWORD cRecipients; 1467 PCERT_INFO *rgpRecipientCert; 1468 PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients; 1469 DWORD cCertEncoded; 1470 PCERT_BLOB rgCertEncoded; 1471 DWORD cCrlEncoded; 1472 PCRL_BLOB rgCrlEncoded; 1473 DWORD cAttrCertEncoded; 1474 PCERT_BLOB rgAttrCertEncoded; 1475 DWORD cUnprotectedAttr; 1476 PCRYPT_ATTRIBUTE rgUnprotectedAttr; 1477 } CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS; 1478 1479 typedef struct _CEnvelopedEncodeMsg 1480 { 1481 CryptMsgBase base; 1482 CRYPT_ALGORITHM_IDENTIFIER algo; 1483 HCRYPTPROV prov; 1484 HCRYPTKEY key; 1485 DWORD cRecipientInfo; 1486 CMSG_KEY_TRANS_RECIPIENT_INFO *recipientInfo; 1487 CRYPT_DATA_BLOB data; 1488 } CEnvelopedEncodeMsg; 1489 1490 static BOOL CRYPT_ConstructAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER *out, 1491 const CRYPT_ALGORITHM_IDENTIFIER *in) 1492 { 1493 out->pszObjId = CryptMemAlloc(strlen(in->pszObjId) + 1); 1494 if (out->pszObjId) 1495 { 1496 strcpy(out->pszObjId, in->pszObjId); 1497 return CRYPT_ConstructBlob(&out->Parameters, &in->Parameters); 1498 } 1499 else 1500 return FALSE; 1501 } 1502 1503 static BOOL CRYPT_ConstructBitBlob(CRYPT_BIT_BLOB *out, const CRYPT_BIT_BLOB *in) 1504 { 1505 out->cbData = in->cbData; 1506 out->cUnusedBits = in->cUnusedBits; 1507 if (out->cbData) 1508 { 1509 out->pbData = CryptMemAlloc(out->cbData); 1510 if (out->pbData) 1511 memcpy(out->pbData, in->pbData, out->cbData); 1512 else 1513 return FALSE; 1514 } 1515 else 1516 out->pbData = NULL; 1517 return TRUE; 1518 } 1519 1520 static BOOL CRYPT_GenKey(CMSG_CONTENT_ENCRYPT_INFO *info, ALG_ID algID) 1521 { 1522 static HCRYPTOIDFUNCSET set = NULL; 1523 PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY genKeyFunc = NULL; 1524 HCRYPTOIDFUNCADDR hFunc; 1525 BOOL ret; 1526 1527 if (!set) 1528 set = CryptInitOIDFunctionSet(CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC, 0); 1529 CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 1530 info->ContentEncryptionAlgorithm.pszObjId, 0, (void **)&genKeyFunc, &hFunc); 1531 if (genKeyFunc) 1532 { 1533 ret = genKeyFunc(info, 0, NULL); 1534 CryptFreeOIDFunctionAddress(hFunc, 0); 1535 } 1536 else 1537 ret = CryptGenKey(info->hCryptProv, algID, CRYPT_EXPORTABLE, 1538 &info->hContentEncryptKey); 1539 return ret; 1540 } 1541 1542 static BOOL WINAPI CRYPT_ExportKeyTrans( 1543 PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo, 1544 PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo, 1545 PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo, 1546 DWORD dwFlags, void *pvReserved) 1547 { 1548 CERT_PUBLIC_KEY_INFO keyInfo; 1549 HCRYPTKEY expKey; 1550 BOOL ret; 1551 1552 ret = CRYPT_ConstructAlgorithmId(&keyInfo.Algorithm, 1553 &pKeyTransEncodeInfo->KeyEncryptionAlgorithm); 1554 if (ret) 1555 CRYPT_ConstructBitBlob(&keyInfo.PublicKey, 1556 &pKeyTransEncodeInfo->RecipientPublicKey); 1557 1558 if (ret) 1559 ret = CryptImportPublicKeyInfo(pKeyTransEncodeInfo->hCryptProv, 1560 X509_ASN_ENCODING, &keyInfo, &expKey); 1561 if (ret) 1562 { 1563 DWORD size; 1564 1565 ret = CryptExportKey(pContentEncryptInfo->hContentEncryptKey, expKey, 1566 SIMPLEBLOB, 0, NULL, &size); 1567 if (ret) 1568 { 1569 BYTE *keyBlob; 1570 1571 keyBlob = CryptMemAlloc(size); 1572 if (keyBlob) 1573 { 1574 ret = CryptExportKey(pContentEncryptInfo->hContentEncryptKey, 1575 expKey, SIMPLEBLOB, 0, keyBlob, &size); 1576 if (ret) 1577 { 1578 DWORD head = sizeof(BLOBHEADER) + sizeof(ALG_ID); 1579 1580 pKeyTransEncryptInfo->EncryptedKey.pbData = 1581 CryptMemAlloc(size - head); 1582 if (pKeyTransEncryptInfo->EncryptedKey.pbData) 1583 { 1584 DWORD i, k = 0; 1585 1586 pKeyTransEncryptInfo->EncryptedKey.cbData = size - head; 1587 for (i = size - 1; i >= head; --i, ++k) 1588 pKeyTransEncryptInfo->EncryptedKey.pbData[k] = 1589 keyBlob[i]; 1590 } 1591 else 1592 ret = FALSE; 1593 } 1594 CryptMemFree(keyBlob); 1595 } 1596 else 1597 ret = FALSE; 1598 } 1599 CryptDestroyKey(expKey); 1600 } 1601 1602 CryptMemFree(keyInfo.PublicKey.pbData); 1603 CryptMemFree(keyInfo.Algorithm.pszObjId); 1604 CryptMemFree(keyInfo.Algorithm.Parameters.pbData); 1605 return ret; 1606 } 1607 1608 static BOOL CRYPT_ExportEncryptedKey(CMSG_CONTENT_ENCRYPT_INFO *info, DWORD i, 1609 CRYPT_DATA_BLOB *key) 1610 { 1611 static HCRYPTOIDFUNCSET set = NULL; 1612 PFN_CMSG_EXPORT_KEY_TRANS exportKeyFunc = NULL; 1613 HCRYPTOIDFUNCADDR hFunc = NULL; 1614 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *encodeInfo = 1615 info->rgCmsRecipients[i].u.pKeyTrans; 1616 CMSG_KEY_TRANS_ENCRYPT_INFO encryptInfo; 1617 BOOL ret; 1618 1619 memset(&encryptInfo, 0, sizeof(encryptInfo)); 1620 encryptInfo.cbSize = sizeof(encryptInfo); 1621 encryptInfo.dwRecipientIndex = i; 1622 ret = CRYPT_ConstructAlgorithmId(&encryptInfo.KeyEncryptionAlgorithm, 1623 &encodeInfo->KeyEncryptionAlgorithm); 1624 1625 if (!set) 1626 set = CryptInitOIDFunctionSet(CMSG_OID_EXPORT_KEY_TRANS_FUNC, 0); 1627 CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 1628 encryptInfo.KeyEncryptionAlgorithm.pszObjId, 0, (void **)&exportKeyFunc, 1629 &hFunc); 1630 if (!exportKeyFunc) 1631 exportKeyFunc = CRYPT_ExportKeyTrans; 1632 if (ret) 1633 { 1634 ret = exportKeyFunc(info, encodeInfo, &encryptInfo, 0, NULL); 1635 if (ret) 1636 { 1637 key->cbData = encryptInfo.EncryptedKey.cbData; 1638 key->pbData = encryptInfo.EncryptedKey.pbData; 1639 } 1640 } 1641 if (hFunc) 1642 CryptFreeOIDFunctionAddress(hFunc, 0); 1643 1644 CryptMemFree(encryptInfo.KeyEncryptionAlgorithm.pszObjId); 1645 CryptMemFree(encryptInfo.KeyEncryptionAlgorithm.Parameters.pbData); 1646 return ret; 1647 } 1648 1649 static LPVOID WINAPI mem_alloc(size_t size) 1650 { 1651 return HeapAlloc(GetProcessHeap(), 0, size); 1652 } 1653 1654 static VOID WINAPI mem_free(LPVOID pv) 1655 { 1656 HeapFree(GetProcessHeap(), 0, pv); 1657 } 1658 1659 1660 static BOOL CContentEncryptInfo_Construct(CMSG_CONTENT_ENCRYPT_INFO *info, 1661 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS *in, HCRYPTPROV prov) 1662 { 1663 BOOL ret; 1664 1665 info->cbSize = sizeof(CMSG_CONTENT_ENCRYPT_INFO); 1666 info->hCryptProv = prov; 1667 ret = CRYPT_ConstructAlgorithmId(&info->ContentEncryptionAlgorithm, 1668 &in->ContentEncryptionAlgorithm); 1669 info->pvEncryptionAuxInfo = in->pvEncryptionAuxInfo; 1670 info->cRecipients = in->cRecipients; 1671 if (ret) 1672 { 1673 info->rgCmsRecipients = CryptMemAlloc(in->cRecipients * 1674 sizeof(CMSG_RECIPIENT_ENCODE_INFO)); 1675 if (info->rgCmsRecipients) 1676 { 1677 DWORD i; 1678 1679 for (i = 0; ret && i < in->cRecipients; ++i) 1680 { 1681 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *encodeInfo; 1682 CERT_INFO *cert = in->rgpRecipientCert[i]; 1683 1684 info->rgCmsRecipients[i].dwRecipientChoice = 1685 CMSG_KEY_TRANS_RECIPIENT; 1686 encodeInfo = CryptMemAlloc(sizeof(*encodeInfo)); 1687 info->rgCmsRecipients[i].u.pKeyTrans = encodeInfo; 1688 if (encodeInfo) 1689 { 1690 encodeInfo->cbSize = sizeof(*encodeInfo); 1691 ret = CRYPT_ConstructAlgorithmId( 1692 &encodeInfo->KeyEncryptionAlgorithm, 1693 &cert->SubjectPublicKeyInfo.Algorithm); 1694 encodeInfo->pvKeyEncryptionAuxInfo = NULL; 1695 encodeInfo->hCryptProv = prov; 1696 if (ret) 1697 ret = CRYPT_ConstructBitBlob( 1698 &encodeInfo->RecipientPublicKey, 1699 &cert->SubjectPublicKeyInfo.PublicKey); 1700 if (ret) 1701 ret = CRYPT_ConstructBlob( 1702 &encodeInfo->RecipientId.u.IssuerSerialNumber.Issuer, 1703 &cert->Issuer); 1704 if (ret) 1705 ret = CRYPT_ConstructBlob( 1706 &encodeInfo->RecipientId.u.IssuerSerialNumber.SerialNumber, 1707 &cert->SerialNumber); 1708 } 1709 else 1710 ret = FALSE; 1711 } 1712 } 1713 else 1714 ret = FALSE; 1715 } 1716 info->pfnAlloc = mem_alloc; 1717 info->pfnFree = mem_free; 1718 return ret; 1719 } 1720 1721 static void CContentEncryptInfo_Free(CMSG_CONTENT_ENCRYPT_INFO *info) 1722 { 1723 CryptMemFree(info->ContentEncryptionAlgorithm.pszObjId); 1724 CryptMemFree(info->ContentEncryptionAlgorithm.Parameters.pbData); 1725 if (info->rgCmsRecipients) 1726 { 1727 DWORD i; 1728 1729 for (i = 0; i < info->cRecipients; ++i) 1730 { 1731 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *encodeInfo = 1732 info->rgCmsRecipients[i].u.pKeyTrans; 1733 1734 CryptMemFree(encodeInfo->KeyEncryptionAlgorithm.pszObjId); 1735 CryptMemFree(encodeInfo->KeyEncryptionAlgorithm.Parameters.pbData); 1736 CryptMemFree(encodeInfo->RecipientPublicKey.pbData); 1737 CryptMemFree( 1738 encodeInfo->RecipientId.u.IssuerSerialNumber.Issuer.pbData); 1739 CryptMemFree( 1740 encodeInfo->RecipientId.u.IssuerSerialNumber.SerialNumber.pbData); 1741 CryptMemFree(encodeInfo); 1742 } 1743 CryptMemFree(info->rgCmsRecipients); 1744 } 1745 } 1746 1747 static BOOL CRecipientInfo_Construct(CMSG_KEY_TRANS_RECIPIENT_INFO *info, 1748 const CERT_INFO *cert, CRYPT_DATA_BLOB *key) 1749 { 1750 BOOL ret; 1751 1752 info->dwVersion = CMSG_KEY_TRANS_PKCS_1_5_VERSION; 1753 info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 1754 ret = CRYPT_ConstructBlob(&info->RecipientId.u.IssuerSerialNumber.Issuer, 1755 &cert->Issuer); 1756 if (ret) 1757 ret = CRYPT_ConstructBlob( 1758 &info->RecipientId.u.IssuerSerialNumber.SerialNumber, 1759 &cert->SerialNumber); 1760 if (ret) 1761 ret = CRYPT_ConstructAlgorithmId(&info->KeyEncryptionAlgorithm, 1762 &cert->SubjectPublicKeyInfo.Algorithm); 1763 info->EncryptedKey.cbData = key->cbData; 1764 info->EncryptedKey.pbData = key->pbData; 1765 return ret; 1766 } 1767 1768 static void CRecipientInfo_Free(CMSG_KEY_TRANS_RECIPIENT_INFO *info) 1769 { 1770 CryptMemFree(info->RecipientId.u.IssuerSerialNumber.Issuer.pbData); 1771 CryptMemFree(info->RecipientId.u.IssuerSerialNumber.SerialNumber.pbData); 1772 CryptMemFree(info->KeyEncryptionAlgorithm.pszObjId); 1773 CryptMemFree(info->KeyEncryptionAlgorithm.Parameters.pbData); 1774 CryptMemFree(info->EncryptedKey.pbData); 1775 } 1776 1777 static void CEnvelopedEncodeMsg_Close(HCRYPTMSG hCryptMsg) 1778 { 1779 CEnvelopedEncodeMsg *msg = hCryptMsg; 1780 1781 CryptMemFree(msg->algo.pszObjId); 1782 CryptMemFree(msg->algo.Parameters.pbData); 1783 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) 1784 CryptReleaseContext(msg->prov, 0); 1785 CryptDestroyKey(msg->key); 1786 if (msg->recipientInfo) 1787 { 1788 DWORD i; 1789 1790 for (i = 0; i < msg->cRecipientInfo; ++i) 1791 CRecipientInfo_Free(&msg->recipientInfo[i]); 1792 CryptMemFree(msg->recipientInfo); 1793 } 1794 CryptMemFree(msg->data.pbData); 1795 } 1796 1797 static BOOL CEnvelopedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 1798 DWORD dwIndex, void *pvData, DWORD *pcbData) 1799 { 1800 CEnvelopedEncodeMsg *msg = hCryptMsg; 1801 BOOL ret = FALSE; 1802 1803 switch (dwParamType) 1804 { 1805 case CMSG_BARE_CONTENT_PARAM: 1806 if (msg->base.streamed) 1807 SetLastError(E_INVALIDARG); 1808 else 1809 { 1810 char oid_rsa_data[] = szOID_RSA_data; 1811 CRYPT_ENVELOPED_DATA envelopedData = { 1812 CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION, msg->cRecipientInfo, 1813 msg->recipientInfo, { oid_rsa_data, { 1814 msg->algo.pszObjId, 1815 { msg->algo.Parameters.cbData, msg->algo.Parameters.pbData } 1816 }, 1817 { msg->data.cbData, msg->data.pbData } 1818 } 1819 }; 1820 1821 ret = CRYPT_AsnEncodePKCSEnvelopedData(&envelopedData, pvData, 1822 pcbData); 1823 } 1824 break; 1825 case CMSG_CONTENT_PARAM: 1826 { 1827 CRYPT_CONTENT_INFO info; 1828 1829 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL, 1830 &info.Content.cbData); 1831 if (ret) 1832 { 1833 info.Content.pbData = CryptMemAlloc(info.Content.cbData); 1834 if (info.Content.pbData) 1835 { 1836 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, 1837 info.Content.pbData, &info.Content.cbData); 1838 if (ret) 1839 { 1840 char oid_rsa_enveloped[] = szOID_RSA_envelopedData; 1841 1842 info.pszObjId = oid_rsa_enveloped; 1843 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, 1844 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData); 1845 } 1846 CryptMemFree(info.Content.pbData); 1847 } 1848 else 1849 ret = FALSE; 1850 } 1851 break; 1852 } 1853 default: 1854 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 1855 } 1856 return ret; 1857 } 1858 1859 static BOOL CEnvelopedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 1860 DWORD cbData, BOOL fFinal) 1861 { 1862 CEnvelopedEncodeMsg *msg = hCryptMsg; 1863 BOOL ret = FALSE; 1864 1865 if (msg->base.state == MsgStateFinalized) 1866 SetLastError(CRYPT_E_MSG_ERROR); 1867 else if (msg->base.streamed) 1868 { 1869 FIXME("streamed stub\n"); 1870 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated; 1871 ret = TRUE; 1872 } 1873 else 1874 { 1875 if (!fFinal) 1876 { 1877 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 1878 SetLastError(E_INVALIDARG); 1879 else 1880 SetLastError(CRYPT_E_MSG_ERROR); 1881 } 1882 else 1883 { 1884 if (cbData) 1885 { 1886 DWORD dataLen = cbData; 1887 1888 msg->data.cbData = cbData; 1889 msg->data.pbData = CryptMemAlloc(cbData); 1890 if (msg->data.pbData) 1891 { 1892 memcpy(msg->data.pbData, pbData, cbData); 1893 ret = CryptEncrypt(msg->key, 0, TRUE, 0, msg->data.pbData, 1894 &dataLen, msg->data.cbData); 1895 msg->data.cbData = dataLen; 1896 if (dataLen > cbData) 1897 { 1898 msg->data.pbData = CryptMemRealloc(msg->data.pbData, 1899 dataLen); 1900 if (msg->data.pbData) 1901 { 1902 dataLen = cbData; 1903 ret = CryptEncrypt(msg->key, 0, TRUE, 0, 1904 msg->data.pbData, &dataLen, msg->data.cbData); 1905 } 1906 else 1907 ret = FALSE; 1908 } 1909 if (!ret) 1910 CryptMemFree(msg->data.pbData); 1911 } 1912 else 1913 ret = FALSE; 1914 if (!ret) 1915 { 1916 msg->data.cbData = 0; 1917 msg->data.pbData = NULL; 1918 } 1919 } 1920 else 1921 ret = TRUE; 1922 msg->base.state = MsgStateFinalized; 1923 } 1924 } 1925 return ret; 1926 } 1927 1928 static HCRYPTMSG CEnvelopedEncodeMsg_Open(DWORD dwFlags, 1929 const void *pvMsgEncodeInfo, LPCSTR pszInnerContentObjID, 1930 PCMSG_STREAM_INFO pStreamInfo) 1931 { 1932 CEnvelopedEncodeMsg *msg; 1933 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS *info = pvMsgEncodeInfo; 1934 HCRYPTPROV prov; 1935 ALG_ID algID; 1936 1937 if (info->cbSize != sizeof(CMSG_ENVELOPED_ENCODE_INFO) && 1938 info->cbSize != sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS)) 1939 { 1940 SetLastError(E_INVALIDARG); 1941 return NULL; 1942 } 1943 if (info->cbSize == sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS)) 1944 FIXME("CMS fields unsupported\n"); 1945 if (!(algID = CertOIDToAlgId(info->ContentEncryptionAlgorithm.pszObjId))) 1946 { 1947 SetLastError(CRYPT_E_UNKNOWN_ALGO); 1948 return NULL; 1949 } 1950 if (info->cRecipients && !info->rgpRecipientCert) 1951 { 1952 SetLastError(E_INVALIDARG); 1953 return NULL; 1954 } 1955 if (info->hCryptProv) 1956 prov = info->hCryptProv; 1957 else 1958 { 1959 prov = CRYPT_GetDefaultProvider(); 1960 dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; 1961 } 1962 msg = CryptMemAlloc(sizeof(CEnvelopedEncodeMsg)); 1963 if (msg) 1964 { 1965 CRYPT_DATA_BLOB encryptedKey = { 0, NULL }; 1966 CMSG_CONTENT_ENCRYPT_INFO encryptInfo; 1967 BOOL ret; 1968 DWORD i; 1969 1970 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 1971 CEnvelopedEncodeMsg_Close, CEnvelopedEncodeMsg_GetParam, 1972 CEnvelopedEncodeMsg_Update, CRYPT_DefaultMsgControl); 1973 ret = CRYPT_ConstructAlgorithmId(&msg->algo, 1974 &info->ContentEncryptionAlgorithm); 1975 msg->prov = prov; 1976 msg->data.cbData = 0; 1977 msg->data.pbData = NULL; 1978 msg->cRecipientInfo = info->cRecipients; 1979 msg->recipientInfo = CryptMemAlloc(info->cRecipients * 1980 sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO)); 1981 if (!msg->recipientInfo) 1982 ret = FALSE; 1983 memset(&encryptInfo, 0, sizeof(encryptInfo)); 1984 if (ret) 1985 { 1986 ret = CContentEncryptInfo_Construct(&encryptInfo, info, prov); 1987 if (ret) 1988 { 1989 ret = CRYPT_GenKey(&encryptInfo, algID); 1990 if (ret) 1991 msg->key = encryptInfo.hContentEncryptKey; 1992 } 1993 } 1994 for (i = 0; ret && i < msg->cRecipientInfo; ++i) 1995 { 1996 ret = CRYPT_ExportEncryptedKey(&encryptInfo, i, &encryptedKey); 1997 if (ret) 1998 ret = CRecipientInfo_Construct(&msg->recipientInfo[i], 1999 info->rgpRecipientCert[i], &encryptedKey); 2000 } 2001 CContentEncryptInfo_Free(&encryptInfo); 2002 if (!ret) 2003 { 2004 CryptMsgClose(msg); 2005 msg = NULL; 2006 } 2007 } 2008 if (!msg && (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)) 2009 CryptReleaseContext(prov, 0); 2010 return msg; 2011 } 2012 2013 HCRYPTMSG WINAPI CryptMsgOpenToEncode(DWORD dwMsgEncodingType, DWORD dwFlags, 2014 DWORD dwMsgType, const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID, 2015 PCMSG_STREAM_INFO pStreamInfo) 2016 { 2017 HCRYPTMSG msg = NULL; 2018 2019 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType, dwFlags, 2020 dwMsgType, pvMsgEncodeInfo, debugstr_a(pszInnerContentObjID), pStreamInfo); 2021 2022 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING) 2023 { 2024 SetLastError(E_INVALIDARG); 2025 return NULL; 2026 } 2027 switch (dwMsgType) 2028 { 2029 case CMSG_DATA: 2030 msg = CDataEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, 2031 pszInnerContentObjID, pStreamInfo); 2032 break; 2033 case CMSG_HASHED: 2034 msg = CHashEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, 2035 pszInnerContentObjID, pStreamInfo); 2036 break; 2037 case CMSG_SIGNED: 2038 msg = CSignedEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, 2039 pszInnerContentObjID, pStreamInfo); 2040 break; 2041 case CMSG_ENVELOPED: 2042 msg = CEnvelopedEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, 2043 pszInnerContentObjID, pStreamInfo); 2044 break; 2045 case CMSG_SIGNED_AND_ENVELOPED: 2046 case CMSG_ENCRYPTED: 2047 /* defined but invalid, fall through */ 2048 default: 2049 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 2050 } 2051 return msg; 2052 } 2053 2054 typedef struct _CEnvelopedDecodeMsg 2055 { 2056 CRYPT_ENVELOPED_DATA *data; 2057 HCRYPTPROV crypt_prov; 2058 CRYPT_DATA_BLOB content; 2059 BOOL decrypted; 2060 } CEnvelopedDecodeMsg; 2061 2062 typedef struct _CDecodeMsg 2063 { 2064 CryptMsgBase base; 2065 DWORD type; 2066 HCRYPTPROV crypt_prov; 2067 union { 2068 HCRYPTHASH hash; 2069 CSignedMsgData signed_data; 2070 CEnvelopedDecodeMsg enveloped_data; 2071 } u; 2072 CRYPT_DATA_BLOB msg_data; 2073 CRYPT_DATA_BLOB detached_data; 2074 CONTEXT_PROPERTY_LIST *properties; 2075 } CDecodeMsg; 2076 2077 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg) 2078 { 2079 CDecodeMsg *msg = hCryptMsg; 2080 2081 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) 2082 CryptReleaseContext(msg->crypt_prov, 0); 2083 switch (msg->type) 2084 { 2085 case CMSG_HASHED: 2086 if (msg->u.hash) 2087 CryptDestroyHash(msg->u.hash); 2088 break; 2089 case CMSG_ENVELOPED: 2090 if (msg->u.enveloped_data.crypt_prov) 2091 CryptReleaseContext(msg->u.enveloped_data.crypt_prov, 0); 2092 LocalFree(msg->u.enveloped_data.data); 2093 CryptMemFree(msg->u.enveloped_data.content.pbData); 2094 break; 2095 case CMSG_SIGNED: 2096 if (msg->u.signed_data.info) 2097 { 2098 LocalFree(msg->u.signed_data.info); 2099 CSignedMsgData_CloseHandles(&msg->u.signed_data); 2100 } 2101 break; 2102 } 2103 CryptMemFree(msg->msg_data.pbData); 2104 CryptMemFree(msg->detached_data.pbData); 2105 ContextPropertyList_Free(msg->properties); 2106 } 2107 2108 static BOOL CDecodeMsg_CopyData(CRYPT_DATA_BLOB *blob, const BYTE *pbData, 2109 DWORD cbData) 2110 { 2111 BOOL ret = TRUE; 2112 2113 if (cbData) 2114 { 2115 if (blob->cbData) 2116 blob->pbData = CryptMemRealloc(blob->pbData, 2117 blob->cbData + cbData); 2118 else 2119 blob->pbData = CryptMemAlloc(cbData); 2120 if (blob->pbData) 2121 { 2122 memcpy(blob->pbData + blob->cbData, pbData, cbData); 2123 blob->cbData += cbData; 2124 } 2125 else 2126 ret = FALSE; 2127 } 2128 return ret; 2129 } 2130 2131 static BOOL CDecodeMsg_DecodeDataContent(CDecodeMsg *msg, const CRYPT_DER_BLOB *blob) 2132 { 2133 BOOL ret; 2134 CRYPT_DATA_BLOB *data; 2135 DWORD size; 2136 2137 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, 2138 blob->pbData, blob->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &data, &size); 2139 if (ret) 2140 { 2141 ret = ContextPropertyList_SetProperty(msg->properties, 2142 CMSG_CONTENT_PARAM, data->pbData, data->cbData); 2143 LocalFree(data); 2144 } 2145 return ret; 2146 } 2147 2148 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg *msg, DWORD param, 2149 const CRYPT_ALGORITHM_IDENTIFIER *id) 2150 { 2151 static const BYTE nullParams[] = { ASN_NULL, 0 }; 2152 CRYPT_ALGORITHM_IDENTIFIER *copy; 2153 DWORD len = sizeof(CRYPT_ALGORITHM_IDENTIFIER); 2154 2155 /* Linearize algorithm id */ 2156 len += strlen(id->pszObjId) + 1; 2157 len += id->Parameters.cbData; 2158 copy = CryptMemAlloc(len); 2159 if (copy) 2160 { 2161 copy->pszObjId = 2162 (LPSTR)((BYTE *)copy + sizeof(CRYPT_ALGORITHM_IDENTIFIER)); 2163 strcpy(copy->pszObjId, id->pszObjId); 2164 copy->Parameters.pbData = (BYTE *)copy->pszObjId + strlen(id->pszObjId) 2165 + 1; 2166 /* Trick: omit NULL parameters */ 2167 if (id->Parameters.cbData == sizeof(nullParams) && 2168 !memcmp(id->Parameters.pbData, nullParams, sizeof(nullParams))) 2169 { 2170 copy->Parameters.cbData = 0; 2171 len -= sizeof(nullParams); 2172 } 2173 else 2174 copy->Parameters.cbData = id->Parameters.cbData; 2175 if (copy->Parameters.cbData) 2176 memcpy(copy->Parameters.pbData, id->Parameters.pbData, 2177 id->Parameters.cbData); 2178 ContextPropertyList_SetProperty(msg->properties, param, (BYTE *)copy, 2179 len); 2180 CryptMemFree(copy); 2181 } 2182 } 2183 2184 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER *id) 2185 { 2186 id->pszObjId = (LPSTR)((BYTE *)id + sizeof(CRYPT_ALGORITHM_IDENTIFIER)); 2187 id->Parameters.pbData = (BYTE *)id->pszObjId + strlen(id->pszObjId) + 1; 2188 } 2189 2190 static BOOL CDecodeMsg_DecodeHashedContent(CDecodeMsg *msg, 2191 const CRYPT_DER_BLOB *blob) 2192 { 2193 BOOL ret; 2194 CRYPT_DIGESTED_DATA *digestedData; 2195 DWORD size; 2196 2197 ret = CRYPT_AsnDecodePKCSDigestedData(blob->pbData, blob->cbData, 2198 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_DIGESTED_DATA *)&digestedData, 2199 &size); 2200 if (ret) 2201 { 2202 ContextPropertyList_SetProperty(msg->properties, CMSG_VERSION_PARAM, 2203 (const BYTE *)&digestedData->version, sizeof(digestedData->version)); 2204 CDecodeMsg_SaveAlgorithmID(msg, CMSG_HASH_ALGORITHM_PARAM, 2205 &digestedData->DigestAlgorithm); 2206 ContextPropertyList_SetProperty(msg->properties, 2207 CMSG_INNER_CONTENT_TYPE_PARAM, 2208 (const BYTE *)digestedData->ContentInfo.pszObjId, 2209 digestedData->ContentInfo.pszObjId ? 2210 strlen(digestedData->ContentInfo.pszObjId) + 1 : 0); 2211 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG)) 2212 { 2213 if (digestedData->ContentInfo.Content.cbData) 2214 CDecodeMsg_DecodeDataContent(msg, 2215 &digestedData->ContentInfo.Content); 2216 else 2217 ContextPropertyList_SetProperty(msg->properties, 2218 CMSG_CONTENT_PARAM, NULL, 0); 2219 } 2220 ContextPropertyList_SetProperty(msg->properties, CMSG_HASH_DATA_PARAM, 2221 digestedData->hash.pbData, digestedData->hash.cbData); 2222 LocalFree(digestedData); 2223 } 2224 return ret; 2225 } 2226 2227 static BOOL CDecodeMsg_DecodeEnvelopedContent(CDecodeMsg *msg, 2228 const CRYPT_DER_BLOB *blob) 2229 { 2230 BOOL ret; 2231 CRYPT_ENVELOPED_DATA *envelopedData; 2232 DWORD size; 2233 2234 ret = CRYPT_AsnDecodePKCSEnvelopedData(blob->pbData, blob->cbData, 2235 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_ENVELOPED_DATA *)&envelopedData, 2236 &size); 2237 if (ret) 2238 msg->u.enveloped_data.data = envelopedData; 2239 return ret; 2240 } 2241 2242 static BOOL CDecodeMsg_DecodeSignedContent(CDecodeMsg *msg, 2243 const CRYPT_DER_BLOB *blob) 2244 { 2245 BOOL ret; 2246 CRYPT_SIGNED_INFO *signedInfo; 2247 DWORD size; 2248 2249 ret = CRYPT_AsnDecodeCMSSignedInfo(blob->pbData, blob->cbData, 2250 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_SIGNED_INFO *)&signedInfo, 2251 &size); 2252 if (ret) 2253 msg->u.signed_data.info = signedInfo; 2254 return ret; 2255 } 2256 2257 /* Decodes the content in blob as the type given, and updates the value 2258 * (type, parameters, etc.) of msg based on what blob contains. 2259 * It doesn't just use msg's type, to allow a recursive call from an implicitly 2260 * typed message once the outer content info has been decoded. 2261 */ 2262 static BOOL CDecodeMsg_DecodeContent(CDecodeMsg *msg, const CRYPT_DER_BLOB *blob, 2263 DWORD type) 2264 { 2265 BOOL ret; 2266 2267 switch (type) 2268 { 2269 case CMSG_DATA: 2270 if ((ret = CDecodeMsg_DecodeDataContent(msg, blob))) 2271 msg->type = CMSG_DATA; 2272 break; 2273 case CMSG_HASHED: 2274 if ((ret = CDecodeMsg_DecodeHashedContent(msg, blob))) 2275 msg->type = CMSG_HASHED; 2276 break; 2277 case CMSG_ENVELOPED: 2278 if ((ret = CDecodeMsg_DecodeEnvelopedContent(msg, blob))) 2279 msg->type = CMSG_ENVELOPED; 2280 break; 2281 case CMSG_SIGNED: 2282 if ((ret = CDecodeMsg_DecodeSignedContent(msg, blob))) 2283 msg->type = CMSG_SIGNED; 2284 break; 2285 default: 2286 { 2287 CRYPT_CONTENT_INFO *info; 2288 DWORD size; 2289 2290 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, PKCS_CONTENT_INFO, 2291 msg->msg_data.pbData, msg->msg_data.cbData, CRYPT_DECODE_ALLOC_FLAG, 2292 NULL, &info, &size); 2293 if (ret) 2294 { 2295 if (!strcmp(info->pszObjId, szOID_RSA_data)) 2296 ret = CDecodeMsg_DecodeContent(msg, &info->Content, CMSG_DATA); 2297 else if (!strcmp(info->pszObjId, szOID_RSA_digestedData)) 2298 ret = CDecodeMsg_DecodeContent(msg, &info->Content, 2299 CMSG_HASHED); 2300 else if (!strcmp(info->pszObjId, szOID_RSA_envelopedData)) 2301 ret = CDecodeMsg_DecodeContent(msg, &info->Content, 2302 CMSG_ENVELOPED); 2303 else if (!strcmp(info->pszObjId, szOID_RSA_signedData)) 2304 ret = CDecodeMsg_DecodeContent(msg, &info->Content, 2305 CMSG_SIGNED); 2306 else 2307 { 2308 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 2309 ret = FALSE; 2310 } 2311 LocalFree(info); 2312 } 2313 } 2314 } 2315 return ret; 2316 } 2317 2318 static BOOL CDecodeMsg_FinalizeHashedContent(CDecodeMsg *msg, 2319 CRYPT_DER_BLOB *blob) 2320 { 2321 CRYPT_ALGORITHM_IDENTIFIER *hashAlgoID = NULL; 2322 DWORD size = 0; 2323 ALG_ID algID = 0; 2324 BOOL ret; 2325 2326 CryptMsgGetParam(msg, CMSG_HASH_ALGORITHM_PARAM, 0, NULL, &size); 2327 hashAlgoID = CryptMemAlloc(size); 2328 ret = CryptMsgGetParam(msg, CMSG_HASH_ALGORITHM_PARAM, 0, hashAlgoID, 2329 &size); 2330 if (ret) 2331 algID = CertOIDToAlgId(hashAlgoID->pszObjId); 2332 ret = CryptCreateHash(msg->crypt_prov, algID, 0, 0, &msg->u.hash); 2333 if (ret) 2334 { 2335 CRYPT_DATA_BLOB content; 2336 2337 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 2338 { 2339 /* Unlike for non-detached messages, the data were never stored as 2340 * the content param, but were saved in msg->detached_data instead. 2341 */ 2342 content.pbData = msg->detached_data.pbData; 2343 content.cbData = msg->detached_data.cbData; 2344 } 2345 else 2346 ret = ContextPropertyList_FindProperty(msg->properties, 2347 CMSG_CONTENT_PARAM, &content); 2348 if (ret) 2349 ret = CryptHashData(msg->u.hash, content.pbData, content.cbData, 0); 2350 } 2351 CryptMemFree(hashAlgoID); 2352 return ret; 2353 } 2354 2355 static BOOL CDecodeMsg_FinalizeEnvelopedContent(CDecodeMsg *msg, 2356 CRYPT_DER_BLOB *blob) 2357 { 2358 CRYPT_DATA_BLOB *content; 2359 2360 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 2361 content = &msg->detached_data; 2362 else 2363 content = 2364 &msg->u.enveloped_data.data->encryptedContentInfo.encryptedContent; 2365 2366 return CRYPT_ConstructBlob(&msg->u.enveloped_data.content, content); 2367 } 2368 2369 static BOOL CDecodeMsg_FinalizeSignedContent(CDecodeMsg *msg, 2370 CRYPT_DER_BLOB *blob) 2371 { 2372 BOOL ret; 2373 DWORD i, size; 2374 2375 ret = CSignedMsgData_AllocateHandles(&msg->u.signed_data); 2376 for (i = 0; ret && i < msg->u.signed_data.info->cSignerInfo; i++) 2377 ret = CSignedMsgData_ConstructSignerHandles(&msg->u.signed_data, i, 2378 msg->crypt_prov); 2379 if (ret) 2380 { 2381 CRYPT_DATA_BLOB *content; 2382 2383 /* Now that we have all the content, update the hash handles with 2384 * it. If the message is a detached message, the content is stored 2385 * in msg->detached_data rather than in the signed message's 2386 * content. 2387 */ 2388 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 2389 content = &msg->detached_data; 2390 else 2391 content = &msg->u.signed_data.info->content.Content; 2392 if (content->cbData) 2393 { 2394 /* If the message is not detached, have to decode the message's 2395 * content if the type is szOID_RSA_data. 2396 */ 2397 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && 2398 !strcmp(msg->u.signed_data.info->content.pszObjId, 2399 szOID_RSA_data)) 2400 { 2401 CRYPT_DATA_BLOB *rsa_blob; 2402 2403 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, 2404 X509_OCTET_STRING, content->pbData, content->cbData, 2405 CRYPT_DECODE_ALLOC_FLAG, NULL, &rsa_blob, &size); 2406 if (ret) 2407 { 2408 ret = CSignedMsgData_Update(&msg->u.signed_data, 2409 rsa_blob->pbData, rsa_blob->cbData, TRUE, Verify); 2410 LocalFree(rsa_blob); 2411 } 2412 } 2413 else 2414 ret = CSignedMsgData_Update(&msg->u.signed_data, 2415 content->pbData, content->cbData, TRUE, Verify); 2416 } 2417 } 2418 return ret; 2419 } 2420 2421 static BOOL CDecodeMsg_FinalizeContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob) 2422 { 2423 BOOL ret = FALSE; 2424 2425 switch (msg->type) 2426 { 2427 case CMSG_HASHED: 2428 ret = CDecodeMsg_FinalizeHashedContent(msg, blob); 2429 break; 2430 case CMSG_ENVELOPED: 2431 ret = CDecodeMsg_FinalizeEnvelopedContent(msg, blob); 2432 break; 2433 case CMSG_SIGNED: 2434 ret = CDecodeMsg_FinalizeSignedContent(msg, blob); 2435 break; 2436 default: 2437 ret = TRUE; 2438 } 2439 return ret; 2440 } 2441 2442 static BOOL CDecodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 2443 DWORD cbData, BOOL fFinal) 2444 { 2445 CDecodeMsg *msg = hCryptMsg; 2446 BOOL ret = FALSE; 2447 2448 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal); 2449 2450 if (msg->base.state == MsgStateFinalized) 2451 SetLastError(CRYPT_E_MSG_ERROR); 2452 else if (msg->base.streamed) 2453 { 2454 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg, pbData, 2455 cbData, fFinal); 2456 switch (msg->base.state) 2457 { 2458 case MsgStateInit: 2459 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData); 2460 if (fFinal) 2461 { 2462 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 2463 msg->base.state = MsgStateDataFinalized; 2464 else 2465 msg->base.state = MsgStateFinalized; 2466 } 2467 else 2468 msg->base.state = MsgStateUpdated; 2469 break; 2470 case MsgStateUpdated: 2471 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData); 2472 if (fFinal) 2473 { 2474 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 2475 msg->base.state = MsgStateDataFinalized; 2476 else 2477 msg->base.state = MsgStateFinalized; 2478 } 2479 break; 2480 case MsgStateDataFinalized: 2481 ret = CDecodeMsg_CopyData(&msg->detached_data, pbData, cbData); 2482 if (fFinal) 2483 msg->base.state = MsgStateFinalized; 2484 break; 2485 default: 2486 SetLastError(CRYPT_E_MSG_ERROR); 2487 break; 2488 } 2489 } 2490 else 2491 { 2492 if (!fFinal) 2493 SetLastError(CRYPT_E_MSG_ERROR); 2494 else 2495 { 2496 switch (msg->base.state) 2497 { 2498 case MsgStateInit: 2499 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData); 2500 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 2501 msg->base.state = MsgStateDataFinalized; 2502 else 2503 msg->base.state = MsgStateFinalized; 2504 break; 2505 case MsgStateDataFinalized: 2506 ret = CDecodeMsg_CopyData(&msg->detached_data, pbData, cbData); 2507 msg->base.state = MsgStateFinalized; 2508 break; 2509 default: 2510 SetLastError(CRYPT_E_MSG_ERROR); 2511 } 2512 } 2513 } 2514 if (ret && fFinal && 2515 ((msg->base.open_flags & CMSG_DETACHED_FLAG && msg->base.state == 2516 MsgStateDataFinalized) || 2517 (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && msg->base.state == 2518 MsgStateFinalized))) 2519 ret = CDecodeMsg_DecodeContent(msg, &msg->msg_data, msg->type); 2520 if (ret && msg->base.state == MsgStateFinalized) 2521 ret = CDecodeMsg_FinalizeContent(msg, &msg->msg_data); 2522 return ret; 2523 } 2524 2525 static BOOL CDecodeHashMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType, 2526 DWORD dwIndex, void *pvData, DWORD *pcbData) 2527 { 2528 BOOL ret = FALSE; 2529 2530 switch (dwParamType) 2531 { 2532 case CMSG_TYPE_PARAM: 2533 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type)); 2534 break; 2535 case CMSG_HASH_ALGORITHM_PARAM: 2536 { 2537 CRYPT_DATA_BLOB blob; 2538 2539 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType, 2540 &blob); 2541 if (ret) 2542 { 2543 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, blob.cbData); 2544 if (ret && pvData) 2545 CRYPT_FixUpAlgorithmID(pvData); 2546 } 2547 else 2548 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 2549 break; 2550 } 2551 case CMSG_COMPUTED_HASH_PARAM: 2552 ret = CryptGetHashParam(msg->u.hash, HP_HASHVAL, pvData, pcbData, 0); 2553 break; 2554 default: 2555 { 2556 CRYPT_DATA_BLOB blob; 2557 2558 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType, 2559 &blob); 2560 if (ret) 2561 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, blob.cbData); 2562 else 2563 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 2564 } 2565 } 2566 return ret; 2567 } 2568 2569 /* nextData is an in/out parameter - on input it's the memory location in 2570 * which a copy of in's data should be made, and on output it's the memory 2571 * location immediately after out's copy of in's data. 2572 */ 2573 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB *out, 2574 const CRYPT_DATA_BLOB *in, LPBYTE *nextData) 2575 { 2576 out->cbData = in->cbData; 2577 if (in->cbData) 2578 { 2579 out->pbData = *nextData; 2580 memcpy(out->pbData, in->pbData, in->cbData); 2581 *nextData += in->cbData; 2582 } 2583 } 2584 2585 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER *out, 2586 const CRYPT_ALGORITHM_IDENTIFIER *in, LPBYTE *nextData) 2587 { 2588 if (in->pszObjId) 2589 { 2590 out->pszObjId = (LPSTR)*nextData; 2591 strcpy(out->pszObjId, in->pszObjId); 2592 *nextData += strlen(out->pszObjId) + 1; 2593 } 2594 CRYPT_CopyBlob(&out->Parameters, &in->Parameters, nextData); 2595 } 2596 2597 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out, 2598 const CRYPT_ATTRIBUTES *in, LPBYTE *nextData) 2599 { 2600 out->cAttr = in->cAttr; 2601 if (in->cAttr) 2602 { 2603 DWORD i; 2604 2605 *nextData = POINTER_ALIGN_DWORD_PTR(*nextData); 2606 out->rgAttr = (CRYPT_ATTRIBUTE *)*nextData; 2607 *nextData += in->cAttr * sizeof(CRYPT_ATTRIBUTE); 2608 for (i = 0; i < in->cAttr; i++) 2609 { 2610 if (in->rgAttr[i].pszObjId) 2611 { 2612 out->rgAttr[i].pszObjId = (LPSTR)*nextData; 2613 strcpy(out->rgAttr[i].pszObjId, in->rgAttr[i].pszObjId); 2614 *nextData += strlen(in->rgAttr[i].pszObjId) + 1; 2615 } 2616 if (in->rgAttr[i].cValue) 2617 { 2618 DWORD j; 2619 2620 out->rgAttr[i].cValue = in->rgAttr[i].cValue; 2621 *nextData = POINTER_ALIGN_DWORD_PTR(*nextData); 2622 out->rgAttr[i].rgValue = (PCRYPT_DATA_BLOB)*nextData; 2623 *nextData += in->rgAttr[i].cValue * sizeof(CRYPT_DATA_BLOB); 2624 for (j = 0; j < in->rgAttr[i].cValue; j++) 2625 CRYPT_CopyBlob(&out->rgAttr[i].rgValue[j], 2626 &in->rgAttr[i].rgValue[j], nextData); 2627 } 2628 } 2629 } 2630 } 2631 2632 static DWORD CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES *attr) 2633 { 2634 DWORD size = attr->cAttr * sizeof(CRYPT_ATTRIBUTE), i, j; 2635 2636 for (i = 0; i < attr->cAttr; i++) 2637 { 2638 if (attr->rgAttr[i].pszObjId) 2639 size += strlen(attr->rgAttr[i].pszObjId) + 1; 2640 /* align pointer */ 2641 size = ALIGN_DWORD_PTR(size); 2642 size += attr->rgAttr[i].cValue * sizeof(CRYPT_DATA_BLOB); 2643 for (j = 0; j < attr->rgAttr[i].cValue; j++) 2644 size += attr->rgAttr[i].rgValue[j].cbData; 2645 } 2646 /* align pointer again to be conservative */ 2647 size = ALIGN_DWORD_PTR(size); 2648 return size; 2649 } 2650 2651 static DWORD CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB *keyId) 2652 { 2653 static char oid_key_rdn[] = szOID_KEYID_RDN; 2654 DWORD size = 0; 2655 CERT_RDN_ATTR attr; 2656 CERT_RDN rdn = { 1, &attr }; 2657 CERT_NAME_INFO name = { 1, &rdn }; 2658 2659 attr.pszObjId = oid_key_rdn; 2660 attr.dwValueType = CERT_RDN_OCTET_STRING; 2661 attr.Value.cbData = keyId->cbData; 2662 attr.Value.pbData = keyId->pbData; 2663 if (CryptEncodeObject(X509_ASN_ENCODING, X509_NAME, &name, NULL, &size)) 2664 size++; /* Only include size of special zero serial number on success */ 2665 return size; 2666 } 2667 2668 static BOOL CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB *issuer, 2669 CRYPT_INTEGER_BLOB *serialNumber, const CRYPT_DATA_BLOB *keyId, DWORD encodedLen, 2670 LPBYTE *nextData) 2671 { 2672 static char oid_key_rdn[] = szOID_KEYID_RDN; 2673 CERT_RDN_ATTR attr; 2674 CERT_RDN rdn = { 1, &attr }; 2675 CERT_NAME_INFO name = { 1, &rdn }; 2676 BOOL ret; 2677 2678 /* Encode special zero serial number */ 2679 serialNumber->cbData = 1; 2680 serialNumber->pbData = *nextData; 2681 **nextData = 0; 2682 (*nextData)++; 2683 /* Encode issuer */ 2684 issuer->pbData = *nextData; 2685 attr.pszObjId = oid_key_rdn; 2686 attr.dwValueType = CERT_RDN_OCTET_STRING; 2687 attr.Value.cbData = keyId->cbData; 2688 attr.Value.pbData = keyId->pbData; 2689 ret = CryptEncodeObject(X509_ASN_ENCODING, X509_NAME, &name, *nextData, 2690 &encodedLen); 2691 if (ret) 2692 { 2693 *nextData += encodedLen; 2694 issuer->cbData = encodedLen; 2695 } 2696 return ret; 2697 } 2698 2699 static BOOL CRYPT_CopySignerInfo(void *pvData, DWORD *pcbData, 2700 const CMSG_CMS_SIGNER_INFO *in) 2701 { 2702 DWORD size = sizeof(CMSG_SIGNER_INFO), rdnSize = 0; 2703 BOOL ret; 2704 2705 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in); 2706 2707 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 2708 { 2709 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData; 2710 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData; 2711 } 2712 else 2713 { 2714 rdnSize = CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in->SignerId.u.KeyId); 2715 size += rdnSize; 2716 } 2717 if (in->HashAlgorithm.pszObjId) 2718 size += strlen(in->HashAlgorithm.pszObjId) + 1; 2719 size += in->HashAlgorithm.Parameters.cbData; 2720 if (in->HashEncryptionAlgorithm.pszObjId) 2721 size += strlen(in->HashEncryptionAlgorithm.pszObjId) + 1; 2722 size += in->HashEncryptionAlgorithm.Parameters.cbData; 2723 size += in->EncryptedHash.cbData; 2724 /* align pointer */ 2725 size = ALIGN_DWORD_PTR(size); 2726 size += CRYPT_SizeOfAttributes(&in->AuthAttrs); 2727 size += CRYPT_SizeOfAttributes(&in->UnauthAttrs); 2728 if (!pvData) 2729 { 2730 ret = TRUE; 2731 } 2732 else if (*pcbData < size) 2733 { 2734 SetLastError(ERROR_MORE_DATA); 2735 ret = FALSE; 2736 } 2737 else 2738 { 2739 LPBYTE nextData = (BYTE *)pvData + sizeof(CMSG_SIGNER_INFO); 2740 CMSG_SIGNER_INFO *out = pvData; 2741 2742 ret = TRUE; 2743 out->dwVersion = in->dwVersion; 2744 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 2745 { 2746 CRYPT_CopyBlob(&out->Issuer, 2747 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData); 2748 CRYPT_CopyBlob(&out->SerialNumber, 2749 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData); 2750 } 2751 else 2752 ret = CRYPT_CopyKeyIdAsIssuerAndSerial(&out->Issuer, &out->SerialNumber, 2753 &in->SignerId.u.KeyId, rdnSize, &nextData); 2754 if (ret) 2755 { 2756 CRYPT_CopyAlgorithmId(&out->HashAlgorithm, &in->HashAlgorithm, 2757 &nextData); 2758 CRYPT_CopyAlgorithmId(&out->HashEncryptionAlgorithm, 2759 &in->HashEncryptionAlgorithm, &nextData); 2760 CRYPT_CopyBlob(&out->EncryptedHash, &in->EncryptedHash, &nextData); 2761 nextData = POINTER_ALIGN_DWORD_PTR(nextData); 2762 CRYPT_CopyAttributes(&out->AuthAttrs, &in->AuthAttrs, &nextData); 2763 CRYPT_CopyAttributes(&out->UnauthAttrs, &in->UnauthAttrs, &nextData); 2764 } 2765 } 2766 *pcbData = size; 2767 TRACE("returning %d\n", ret); 2768 return ret; 2769 } 2770 2771 static BOOL CRYPT_CopyCMSSignerInfo(void *pvData, DWORD *pcbData, 2772 const CMSG_CMS_SIGNER_INFO *in) 2773 { 2774 DWORD size = sizeof(CMSG_CMS_SIGNER_INFO); 2775 BOOL ret; 2776 2777 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in); 2778 2779 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 2780 { 2781 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData; 2782 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData; 2783 } 2784 else 2785 size += in->SignerId.u.KeyId.cbData; 2786 if (in->HashAlgorithm.pszObjId) 2787 size += strlen(in->HashAlgorithm.pszObjId) + 1; 2788 size += in->HashAlgorithm.Parameters.cbData; 2789 if (in->HashEncryptionAlgorithm.pszObjId) 2790 size += strlen(in->HashEncryptionAlgorithm.pszObjId) + 1; 2791 size += in->HashEncryptionAlgorithm.Parameters.cbData; 2792 size += in->EncryptedHash.cbData; 2793 /* align pointer */ 2794 size = ALIGN_DWORD_PTR(size); 2795 size += CRYPT_SizeOfAttributes(&in->AuthAttrs); 2796 size += CRYPT_SizeOfAttributes(&in->UnauthAttrs); 2797 if (!pvData) 2798 { 2799 *pcbData = size; 2800 ret = TRUE; 2801 } 2802 else if (*pcbData < size) 2803 { 2804 *pcbData = size; 2805 SetLastError(ERROR_MORE_DATA); 2806 ret = FALSE; 2807 } 2808 else 2809 { 2810 LPBYTE nextData = (BYTE *)pvData + sizeof(CMSG_CMS_SIGNER_INFO); 2811 CMSG_CMS_SIGNER_INFO *out = pvData; 2812 2813 out->dwVersion = in->dwVersion; 2814 out->SignerId.dwIdChoice = in->SignerId.dwIdChoice; 2815 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 2816 { 2817 CRYPT_CopyBlob(&out->SignerId.u.IssuerSerialNumber.Issuer, 2818 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData); 2819 CRYPT_CopyBlob(&out->SignerId.u.IssuerSerialNumber.SerialNumber, 2820 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData); 2821 } 2822 else 2823 CRYPT_CopyBlob(&out->SignerId.u.KeyId, &in->SignerId.u.KeyId, &nextData); 2824 CRYPT_CopyAlgorithmId(&out->HashAlgorithm, &in->HashAlgorithm, 2825 &nextData); 2826 CRYPT_CopyAlgorithmId(&out->HashEncryptionAlgorithm, 2827 &in->HashEncryptionAlgorithm, &nextData); 2828 CRYPT_CopyBlob(&out->EncryptedHash, &in->EncryptedHash, &nextData); 2829 nextData = POINTER_ALIGN_DWORD_PTR(nextData); 2830 CRYPT_CopyAttributes(&out->AuthAttrs, &in->AuthAttrs, &nextData); 2831 CRYPT_CopyAttributes(&out->UnauthAttrs, &in->UnauthAttrs, &nextData); 2832 ret = TRUE; 2833 } 2834 TRACE("returning %d\n", ret); 2835 return ret; 2836 } 2837 2838 static BOOL CRYPT_CopySignerCertInfo(void *pvData, DWORD *pcbData, 2839 const CMSG_CMS_SIGNER_INFO *in) 2840 { 2841 DWORD size = sizeof(CERT_INFO), rdnSize = 0; 2842 BOOL ret; 2843 2844 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in); 2845 2846 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 2847 { 2848 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData; 2849 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData; 2850 } 2851 else 2852 { 2853 rdnSize = CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in->SignerId.u.KeyId); 2854 size += rdnSize; 2855 } 2856 if (!pvData) 2857 { 2858 *pcbData = size; 2859 ret = TRUE; 2860 } 2861 else if (*pcbData < size) 2862 { 2863 *pcbData = size; 2864 SetLastError(ERROR_MORE_DATA); 2865 ret = FALSE; 2866 } 2867 else 2868 { 2869 LPBYTE nextData = (BYTE *)pvData + sizeof(CERT_INFO); 2870 CERT_INFO *out = pvData; 2871 2872 memset(out, 0, sizeof(CERT_INFO)); 2873 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 2874 { 2875 CRYPT_CopyBlob(&out->Issuer, 2876 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData); 2877 CRYPT_CopyBlob(&out->SerialNumber, 2878 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData); 2879 ret = TRUE; 2880 } 2881 else 2882 ret = CRYPT_CopyKeyIdAsIssuerAndSerial(&out->Issuer, &out->SerialNumber, 2883 &in->SignerId.u.KeyId, rdnSize, &nextData); 2884 } 2885 TRACE("returning %d\n", ret); 2886 return ret; 2887 } 2888 2889 static BOOL CRYPT_CopyRecipientInfo(void *pvData, DWORD *pcbData, 2890 const CERT_ISSUER_SERIAL_NUMBER *in) 2891 { 2892 DWORD size = sizeof(CERT_INFO); 2893 BOOL ret; 2894 2895 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in); 2896 2897 size += in->SerialNumber.cbData; 2898 size += in->Issuer.cbData; 2899 if (!pvData) 2900 { 2901 *pcbData = size; 2902 ret = TRUE; 2903 } 2904 else if (*pcbData < size) 2905 { 2906 *pcbData = size; 2907 SetLastError(ERROR_MORE_DATA); 2908 ret = FALSE; 2909 } 2910 else 2911 { 2912 LPBYTE nextData = (BYTE *)pvData + sizeof(CERT_INFO); 2913 CERT_INFO *out = pvData; 2914 2915 CRYPT_CopyBlob(&out->SerialNumber, &in->SerialNumber, &nextData); 2916 CRYPT_CopyBlob(&out->Issuer, &in->Issuer, &nextData); 2917 ret = TRUE; 2918 } 2919 TRACE("returning %d\n", ret); 2920 return ret; 2921 } 2922 2923 static BOOL CDecodeEnvelopedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType, 2924 DWORD dwIndex, void *pvData, DWORD *pcbData) 2925 { 2926 BOOL ret = FALSE; 2927 2928 switch (dwParamType) 2929 { 2930 case CMSG_TYPE_PARAM: 2931 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type)); 2932 break; 2933 case CMSG_CONTENT_PARAM: 2934 if (msg->u.enveloped_data.data) 2935 ret = CRYPT_CopyParam(pvData, pcbData, 2936 msg->u.enveloped_data.content.pbData, 2937 msg->u.enveloped_data.content.cbData); 2938 else 2939 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 2940 break; 2941 case CMSG_RECIPIENT_COUNT_PARAM: 2942 if (msg->u.enveloped_data.data) 2943 ret = CRYPT_CopyParam(pvData, pcbData, 2944 &msg->u.enveloped_data.data->cRecipientInfo, sizeof(DWORD)); 2945 else 2946 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 2947 break; 2948 case CMSG_RECIPIENT_INFO_PARAM: 2949 if (msg->u.enveloped_data.data) 2950 { 2951 if (dwIndex < msg->u.enveloped_data.data->cRecipientInfo) 2952 { 2953 PCMSG_KEY_TRANS_RECIPIENT_INFO recipientInfo = 2954 &msg->u.enveloped_data.data->rgRecipientInfo[dwIndex]; 2955 2956 ret = CRYPT_CopyRecipientInfo(pvData, pcbData, 2957 &recipientInfo->RecipientId.u.IssuerSerialNumber); 2958 } 2959 else 2960 SetLastError(CRYPT_E_INVALID_INDEX); 2961 } 2962 else 2963 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 2964 break; 2965 default: 2966 FIXME("unimplemented for %d\n", dwParamType); 2967 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 2968 } 2969 return ret; 2970 } 2971 2972 static BOOL CDecodeSignedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType, 2973 DWORD dwIndex, void *pvData, DWORD *pcbData) 2974 { 2975 BOOL ret = FALSE; 2976 2977 switch (dwParamType) 2978 { 2979 case CMSG_TYPE_PARAM: 2980 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type)); 2981 break; 2982 case CMSG_CONTENT_PARAM: 2983 if (msg->u.signed_data.info) 2984 { 2985 if (!strcmp(msg->u.signed_data.info->content.pszObjId, 2986 szOID_RSA_data)) 2987 { 2988 CRYPT_DATA_BLOB *blob; 2989 DWORD size; 2990 2991 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, 2992 msg->u.signed_data.info->content.Content.pbData, 2993 msg->u.signed_data.info->content.Content.cbData, 2994 CRYPT_DECODE_ALLOC_FLAG, NULL, &blob, &size); 2995 if (ret) 2996 { 2997 ret = CRYPT_CopyParam(pvData, pcbData, blob->pbData, 2998 blob->cbData); 2999 LocalFree(blob); 3000 } 3001 } 3002 else 3003 ret = CRYPT_CopyParam(pvData, pcbData, 3004 msg->u.signed_data.info->content.Content.pbData, 3005 msg->u.signed_data.info->content.Content.cbData); 3006 } 3007 else 3008 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3009 break; 3010 case CMSG_INNER_CONTENT_TYPE_PARAM: 3011 if (msg->u.signed_data.info) 3012 ret = CRYPT_CopyParam(pvData, pcbData, 3013 msg->u.signed_data.info->content.pszObjId, 3014 strlen(msg->u.signed_data.info->content.pszObjId) + 1); 3015 else 3016 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3017 break; 3018 case CMSG_SIGNER_COUNT_PARAM: 3019 if (msg->u.signed_data.info) 3020 ret = CRYPT_CopyParam(pvData, pcbData, 3021 &msg->u.signed_data.info->cSignerInfo, sizeof(DWORD)); 3022 else 3023 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3024 break; 3025 case CMSG_SIGNER_INFO_PARAM: 3026 if (msg->u.signed_data.info) 3027 { 3028 if (dwIndex >= msg->u.signed_data.info->cSignerInfo) 3029 SetLastError(CRYPT_E_INVALID_INDEX); 3030 else 3031 ret = CRYPT_CopySignerInfo(pvData, pcbData, 3032 &msg->u.signed_data.info->rgSignerInfo[dwIndex]); 3033 } 3034 else 3035 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3036 break; 3037 case CMSG_SIGNER_CERT_INFO_PARAM: 3038 if (msg->u.signed_data.info) 3039 { 3040 if (dwIndex >= msg->u.signed_data.info->cSignerInfo) 3041 SetLastError(CRYPT_E_INVALID_INDEX); 3042 else 3043 ret = CRYPT_CopySignerCertInfo(pvData, pcbData, 3044 &msg->u.signed_data.info->rgSignerInfo[dwIndex]); 3045 } 3046 else 3047 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3048 break; 3049 case CMSG_CERT_COUNT_PARAM: 3050 if (msg->u.signed_data.info) 3051 ret = CRYPT_CopyParam(pvData, pcbData, 3052 &msg->u.signed_data.info->cCertEncoded, sizeof(DWORD)); 3053 else 3054 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3055 break; 3056 case CMSG_CERT_PARAM: 3057 if (msg->u.signed_data.info) 3058 { 3059 if (dwIndex >= msg->u.signed_data.info->cCertEncoded) 3060 SetLastError(CRYPT_E_INVALID_INDEX); 3061 else 3062 ret = CRYPT_CopyParam(pvData, pcbData, 3063 msg->u.signed_data.info->rgCertEncoded[dwIndex].pbData, 3064 msg->u.signed_data.info->rgCertEncoded[dwIndex].cbData); 3065 } 3066 else 3067 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3068 break; 3069 case CMSG_CRL_COUNT_PARAM: 3070 if (msg->u.signed_data.info) 3071 ret = CRYPT_CopyParam(pvData, pcbData, 3072 &msg->u.signed_data.info->cCrlEncoded, sizeof(DWORD)); 3073 else 3074 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3075 break; 3076 case CMSG_CRL_PARAM: 3077 if (msg->u.signed_data.info) 3078 { 3079 if (dwIndex >= msg->u.signed_data.info->cCrlEncoded) 3080 SetLastError(CRYPT_E_INVALID_INDEX); 3081 else 3082 ret = CRYPT_CopyParam(pvData, pcbData, 3083 msg->u.signed_data.info->rgCrlEncoded[dwIndex].pbData, 3084 msg->u.signed_data.info->rgCrlEncoded[dwIndex].cbData); 3085 } 3086 else 3087 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3088 break; 3089 case CMSG_COMPUTED_HASH_PARAM: 3090 if (msg->u.signed_data.info) 3091 { 3092 if (dwIndex >= msg->u.signed_data.cSignerHandle) 3093 SetLastError(CRYPT_E_INVALID_INDEX); 3094 else 3095 ret = CryptGetHashParam( 3096 msg->u.signed_data.signerHandles[dwIndex].contentHash, 3097 HP_HASHVAL, pvData, pcbData, 0); 3098 } 3099 else 3100 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3101 break; 3102 case CMSG_ENCODED_SIGNER: 3103 if (msg->u.signed_data.info) 3104 { 3105 if (dwIndex >= msg->u.signed_data.info->cSignerInfo) 3106 SetLastError(CRYPT_E_INVALID_INDEX); 3107 else 3108 ret = CryptEncodeObjectEx( 3109 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CMS_SIGNER_INFO, 3110 &msg->u.signed_data.info->rgSignerInfo[dwIndex], 0, NULL, 3111 pvData, pcbData); 3112 } 3113 else 3114 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3115 break; 3116 case CMSG_ATTR_CERT_COUNT_PARAM: 3117 if (msg->u.signed_data.info) 3118 { 3119 DWORD attrCertCount = 0; 3120 3121 ret = CRYPT_CopyParam(pvData, pcbData, 3122 &attrCertCount, sizeof(DWORD)); 3123 } 3124 else 3125 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3126 break; 3127 case CMSG_ATTR_CERT_PARAM: 3128 if (msg->u.signed_data.info) 3129 SetLastError(CRYPT_E_INVALID_INDEX); 3130 else 3131 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3132 break; 3133 case CMSG_CMS_SIGNER_INFO_PARAM: 3134 if (msg->u.signed_data.info) 3135 { 3136 if (dwIndex >= msg->u.signed_data.info->cSignerInfo) 3137 SetLastError(CRYPT_E_INVALID_INDEX); 3138 else 3139 ret = CRYPT_CopyCMSSignerInfo(pvData, pcbData, 3140 &msg->u.signed_data.info->rgSignerInfo[dwIndex]); 3141 } 3142 else 3143 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3144 break; 3145 default: 3146 FIXME("unimplemented for %d\n", dwParamType); 3147 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3148 } 3149 return ret; 3150 } 3151 3152 static BOOL CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 3153 DWORD dwIndex, void *pvData, DWORD *pcbData) 3154 { 3155 CDecodeMsg *msg = hCryptMsg; 3156 BOOL ret = FALSE; 3157 3158 switch (msg->type) 3159 { 3160 case CMSG_HASHED: 3161 ret = CDecodeHashMsg_GetParam(msg, dwParamType, dwIndex, pvData, 3162 pcbData); 3163 break; 3164 case CMSG_ENVELOPED: 3165 ret = CDecodeEnvelopedMsg_GetParam(msg, dwParamType, dwIndex, pvData, 3166 pcbData); 3167 break; 3168 case CMSG_SIGNED: 3169 ret = CDecodeSignedMsg_GetParam(msg, dwParamType, dwIndex, pvData, 3170 pcbData); 3171 break; 3172 default: 3173 switch (dwParamType) 3174 { 3175 case CMSG_TYPE_PARAM: 3176 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, 3177 sizeof(msg->type)); 3178 break; 3179 default: 3180 { 3181 CRYPT_DATA_BLOB blob; 3182 3183 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType, 3184 &blob); 3185 if (ret) 3186 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, 3187 blob.cbData); 3188 else 3189 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3190 } 3191 } 3192 } 3193 return ret; 3194 } 3195 3196 static BOOL CDecodeHashMsg_VerifyHash(CDecodeMsg *msg) 3197 { 3198 BOOL ret; 3199 CRYPT_DATA_BLOB hashBlob; 3200 3201 ret = ContextPropertyList_FindProperty(msg->properties, 3202 CMSG_HASH_DATA_PARAM, &hashBlob); 3203 if (ret) 3204 { 3205 DWORD computedHashSize = 0; 3206 3207 ret = CDecodeHashMsg_GetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, 3208 &computedHashSize); 3209 if (hashBlob.cbData == computedHashSize) 3210 { 3211 LPBYTE computedHash = CryptMemAlloc(computedHashSize); 3212 3213 if (computedHash) 3214 { 3215 ret = CDecodeHashMsg_GetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, 3216 computedHash, &computedHashSize); 3217 if (ret) 3218 { 3219 if (memcmp(hashBlob.pbData, computedHash, hashBlob.cbData)) 3220 { 3221 SetLastError(CRYPT_E_HASH_VALUE); 3222 ret = FALSE; 3223 } 3224 } 3225 CryptMemFree(computedHash); 3226 } 3227 else 3228 { 3229 SetLastError(ERROR_OUTOFMEMORY); 3230 ret = FALSE; 3231 } 3232 } 3233 else 3234 { 3235 SetLastError(CRYPT_E_HASH_VALUE); 3236 ret = FALSE; 3237 } 3238 } 3239 return ret; 3240 } 3241 3242 static BOOL CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg *msg, 3243 HCRYPTPROV prov, DWORD signerIndex, PCERT_PUBLIC_KEY_INFO keyInfo) 3244 { 3245 HCRYPTKEY key; 3246 BOOL ret; 3247 3248 if (!prov) 3249 prov = msg->crypt_prov; 3250 ret = CryptImportPublicKeyInfo(prov, X509_ASN_ENCODING, keyInfo, &key); 3251 if (ret) 3252 { 3253 HCRYPTHASH hash; 3254 CRYPT_HASH_BLOB reversedHash; 3255 3256 if (msg->u.signed_data.info->rgSignerInfo[signerIndex].AuthAttrs.cAttr) 3257 hash = msg->u.signed_data.signerHandles[signerIndex].authAttrHash; 3258 else 3259 hash = msg->u.signed_data.signerHandles[signerIndex].contentHash; 3260 ret = CRYPT_ConstructBlob(&reversedHash, 3261 &msg->u.signed_data.info->rgSignerInfo[signerIndex].EncryptedHash); 3262 if (ret) 3263 { 3264 CRYPT_ReverseBytes(&reversedHash); 3265 ret = CryptVerifySignatureW(hash, reversedHash.pbData, 3266 reversedHash.cbData, key, NULL, 0); 3267 CryptMemFree(reversedHash.pbData); 3268 } 3269 CryptDestroyKey(key); 3270 } 3271 return ret; 3272 } 3273 3274 static BOOL CDecodeSignedMsg_VerifySignature(CDecodeMsg *msg, PCERT_INFO info) 3275 { 3276 BOOL ret = FALSE; 3277 DWORD i; 3278 3279 if (!msg->u.signed_data.signerHandles) 3280 { 3281 SetLastError(NTE_BAD_SIGNATURE); 3282 return FALSE; 3283 } 3284 for (i = 0; !ret && i < msg->u.signed_data.info->cSignerInfo; i++) 3285 { 3286 PCMSG_CMS_SIGNER_INFO signerInfo = 3287 &msg->u.signed_data.info->rgSignerInfo[i]; 3288 3289 if (signerInfo->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 3290 { 3291 ret = CertCompareCertificateName(X509_ASN_ENCODING, 3292 &signerInfo->SignerId.u.IssuerSerialNumber.Issuer, 3293 &info->Issuer); 3294 if (ret) 3295 { 3296 ret = CertCompareIntegerBlob( 3297 &signerInfo->SignerId.u.IssuerSerialNumber.SerialNumber, 3298 &info->SerialNumber); 3299 if (ret) 3300 break; 3301 } 3302 } 3303 else 3304 { 3305 FIXME("signer %d: unimplemented for key id\n", i); 3306 } 3307 } 3308 if (ret) 3309 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, 0, i, 3310 &info->SubjectPublicKeyInfo); 3311 else 3312 SetLastError(CRYPT_E_SIGNER_NOT_FOUND); 3313 3314 return ret; 3315 } 3316 3317 static BOOL CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg *msg, 3318 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para) 3319 { 3320 BOOL ret = FALSE; 3321 3322 if (para->cbSize != sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA)) 3323 SetLastError(ERROR_INVALID_PARAMETER); 3324 else if (para->dwSignerIndex >= msg->u.signed_data.info->cSignerInfo) 3325 SetLastError(CRYPT_E_SIGNER_NOT_FOUND); 3326 else if (!msg->u.signed_data.signerHandles) 3327 SetLastError(NTE_BAD_SIGNATURE); 3328 else 3329 { 3330 switch (para->dwSignerType) 3331 { 3332 case CMSG_VERIFY_SIGNER_PUBKEY: 3333 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, 3334 para->hCryptProv, para->dwSignerIndex, para->pvSigner); 3335 break; 3336 case CMSG_VERIFY_SIGNER_CERT: 3337 { 3338 PCCERT_CONTEXT cert = para->pvSigner; 3339 3340 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, para->hCryptProv, 3341 para->dwSignerIndex, &cert->pCertInfo->SubjectPublicKeyInfo); 3342 break; 3343 } 3344 default: 3345 FIXME("unimplemented for signer type %d\n", para->dwSignerType); 3346 SetLastError(CRYPT_E_SIGNER_NOT_FOUND); 3347 } 3348 } 3349 return ret; 3350 } 3351 3352 static BOOL WINAPI CRYPT_ImportKeyTrans( 3353 PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm, 3354 PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara, DWORD dwFlags, 3355 void *pvReserved, HCRYPTKEY *phContentEncryptKey) 3356 { 3357 BOOL ret; 3358 HCRYPTKEY key; 3359 3360 ret = CryptGetUserKey(pKeyTransDecryptPara->hCryptProv, 3361 pKeyTransDecryptPara->dwKeySpec ? pKeyTransDecryptPara->dwKeySpec : 3362 AT_KEYEXCHANGE, &key); 3363 if (ret) 3364 { 3365 CMSG_KEY_TRANS_RECIPIENT_INFO *info = 3366 &pKeyTransDecryptPara->pKeyTrans[pKeyTransDecryptPara->dwRecipientIndex]; 3367 CRYPT_DATA_BLOB *encryptedKey = &info->EncryptedKey; 3368 DWORD size = encryptedKey->cbData + sizeof(BLOBHEADER) + sizeof(ALG_ID); 3369 BYTE *keyBlob = CryptMemAlloc(size); 3370 3371 if (keyBlob) 3372 { 3373 DWORD i, k = size - 1; 3374 BLOBHEADER *blobHeader = (BLOBHEADER *)keyBlob; 3375 ALG_ID *algID = (ALG_ID *)(keyBlob + sizeof(BLOBHEADER)); 3376 3377 blobHeader->bType = SIMPLEBLOB; 3378 blobHeader->bVersion = CUR_BLOB_VERSION; 3379 blobHeader->reserved = 0; 3380 blobHeader->aiKeyAlg = CertOIDToAlgId( 3381 pContentEncryptionAlgorithm->pszObjId); 3382 *algID = CertOIDToAlgId(info->KeyEncryptionAlgorithm.pszObjId); 3383 for (i = 0; i < encryptedKey->cbData; ++i, --k) 3384 keyBlob[k] = encryptedKey->pbData[i]; 3385 3386 ret = CryptImportKey(pKeyTransDecryptPara->hCryptProv, keyBlob, 3387 size, key, 0, phContentEncryptKey); 3388 CryptMemFree(keyBlob); 3389 } 3390 else 3391 ret = FALSE; 3392 CryptDestroyKey(key); 3393 } 3394 return ret; 3395 } 3396 3397 static BOOL CRYPT_ImportEncryptedKey(PCRYPT_ALGORITHM_IDENTIFIER contEncrAlg, 3398 PCMSG_CTRL_DECRYPT_PARA para, PCMSG_KEY_TRANS_RECIPIENT_INFO info, 3399 HCRYPTKEY *key) 3400 { 3401 static HCRYPTOIDFUNCSET set = NULL; 3402 PFN_CMSG_IMPORT_KEY_TRANS importKeyFunc = NULL; 3403 HCRYPTOIDFUNCADDR hFunc = NULL; 3404 CMSG_CTRL_KEY_TRANS_DECRYPT_PARA decryptPara; 3405 BOOL ret; 3406 3407 memset(&decryptPara, 0, sizeof(decryptPara)); 3408 decryptPara.cbSize = sizeof(decryptPara); 3409 decryptPara.hCryptProv = para->hCryptProv; 3410 decryptPara.dwKeySpec = para->dwKeySpec; 3411 decryptPara.pKeyTrans = info; 3412 decryptPara.dwRecipientIndex = para->dwRecipientIndex; 3413 3414 if (!set) 3415 set = CryptInitOIDFunctionSet(CMSG_OID_IMPORT_KEY_TRANS_FUNC, 0); 3416 CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, contEncrAlg->pszObjId, 0, 3417 (void **)&importKeyFunc, &hFunc); 3418 if (!importKeyFunc) 3419 importKeyFunc = CRYPT_ImportKeyTrans; 3420 ret = importKeyFunc(contEncrAlg, &decryptPara, 0, NULL, key); 3421 if (hFunc) 3422 CryptFreeOIDFunctionAddress(hFunc, 0); 3423 return ret; 3424 } 3425 3426 static BOOL CDecodeEnvelopedMsg_CrtlDecrypt(CDecodeMsg *msg, 3427 PCMSG_CTRL_DECRYPT_PARA para) 3428 { 3429 BOOL ret = FALSE; 3430 CEnvelopedDecodeMsg *enveloped_data = &msg->u.enveloped_data; 3431 CRYPT_ENVELOPED_DATA *data = enveloped_data->data; 3432 3433 if (para->cbSize != sizeof(CMSG_CTRL_DECRYPT_PARA)) 3434 SetLastError(E_INVALIDARG); 3435 else if (!data) 3436 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3437 else if (para->dwRecipientIndex >= data->cRecipientInfo) 3438 SetLastError(CRYPT_E_INVALID_INDEX); 3439 else if (enveloped_data->decrypted) 3440 SetLastError(CRYPT_E_ALREADY_DECRYPTED); 3441 else if (!para->hCryptProv) 3442 SetLastError(ERROR_INVALID_PARAMETER); 3443 else if (enveloped_data->content.cbData) 3444 { 3445 HCRYPTKEY key; 3446 3447 ret = CRYPT_ImportEncryptedKey( 3448 &data->encryptedContentInfo.contentEncryptionAlgorithm, para, 3449 data->rgRecipientInfo, &key); 3450 if (ret) 3451 { 3452 ret = CryptDecrypt(key, 0, TRUE, 0, enveloped_data->content.pbData, 3453 &enveloped_data->content.cbData); 3454 CryptDestroyKey(key); 3455 } 3456 } 3457 else 3458 ret = TRUE; 3459 if (ret) 3460 enveloped_data->decrypted = TRUE; 3461 return ret; 3462 } 3463 3464 static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags, 3465 DWORD dwCtrlType, const void *pvCtrlPara) 3466 { 3467 CDecodeMsg *msg = hCryptMsg; 3468 BOOL ret = FALSE; 3469 3470 switch (dwCtrlType) 3471 { 3472 case CMSG_CTRL_VERIFY_SIGNATURE: 3473 switch (msg->type) 3474 { 3475 case CMSG_SIGNED: 3476 ret = CDecodeSignedMsg_VerifySignature(msg, (PCERT_INFO)pvCtrlPara); 3477 break; 3478 default: 3479 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3480 } 3481 break; 3482 case CMSG_CTRL_DECRYPT: 3483 switch (msg->type) 3484 { 3485 case CMSG_ENVELOPED: 3486 ret = CDecodeEnvelopedMsg_CrtlDecrypt(msg, 3487 (PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara); 3488 if (ret && (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)) 3489 msg->u.enveloped_data.crypt_prov = 3490 ((PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara)->hCryptProv; 3491 break; 3492 default: 3493 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3494 } 3495 break; 3496 case CMSG_CTRL_VERIFY_HASH: 3497 switch (msg->type) 3498 { 3499 case CMSG_HASHED: 3500 ret = CDecodeHashMsg_VerifyHash(msg); 3501 break; 3502 default: 3503 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3504 } 3505 break; 3506 case CMSG_CTRL_VERIFY_SIGNATURE_EX: 3507 switch (msg->type) 3508 { 3509 case CMSG_SIGNED: 3510 ret = CDecodeSignedMsg_VerifySignatureEx(msg, 3511 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA)pvCtrlPara); 3512 break; 3513 default: 3514 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 3515 } 3516 break; 3517 default: 3518 SetLastError(CRYPT_E_CONTROL_TYPE); 3519 } 3520 return ret; 3521 } 3522 3523 HCRYPTMSG WINAPI CryptMsgOpenToDecode(DWORD dwMsgEncodingType, DWORD dwFlags, 3524 DWORD dwMsgType, HCRYPTPROV_LEGACY hCryptProv, PCERT_INFO pRecipientInfo, 3525 PCMSG_STREAM_INFO pStreamInfo) 3526 { 3527 CDecodeMsg *msg; 3528 3529 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType, 3530 dwFlags, dwMsgType, hCryptProv, pRecipientInfo, pStreamInfo); 3531 3532 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING) 3533 { 3534 SetLastError(E_INVALIDARG); 3535 return NULL; 3536 } 3537 msg = CryptMemAlloc(sizeof(CDecodeMsg)); 3538 if (msg) 3539 { 3540 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 3541 CDecodeMsg_Close, CDecodeMsg_GetParam, CDecodeMsg_Update, 3542 CDecodeMsg_Control); 3543 msg->type = dwMsgType; 3544 if (hCryptProv) 3545 msg->crypt_prov = hCryptProv; 3546 else 3547 { 3548 msg->crypt_prov = CRYPT_GetDefaultProvider(); 3549 msg->base.open_flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; 3550 } 3551 memset(&msg->u, 0, sizeof(msg->u)); 3552 msg->msg_data.cbData = 0; 3553 msg->msg_data.pbData = NULL; 3554 msg->detached_data.cbData = 0; 3555 msg->detached_data.pbData = NULL; 3556 msg->properties = ContextPropertyList_Create(); 3557 } 3558 return msg; 3559 } 3560 3561 HCRYPTMSG WINAPI CryptMsgDuplicate(HCRYPTMSG hCryptMsg) 3562 { 3563 TRACE("(%p)\n", hCryptMsg); 3564 3565 if (hCryptMsg) 3566 { 3567 CryptMsgBase *msg = hCryptMsg; 3568 3569 InterlockedIncrement(&msg->ref); 3570 } 3571 return hCryptMsg; 3572 } 3573 3574 BOOL WINAPI CryptMsgClose(HCRYPTMSG hCryptMsg) 3575 { 3576 TRACE("(%p)\n", hCryptMsg); 3577 3578 if (hCryptMsg) 3579 { 3580 CryptMsgBase *msg = hCryptMsg; 3581 3582 if (InterlockedDecrement(&msg->ref) == 0) 3583 { 3584 TRACE("freeing %p\n", msg); 3585 if (msg->close) 3586 msg->close(msg); 3587 CryptMemFree(msg); 3588 } 3589 } 3590 return TRUE; 3591 } 3592 3593 BOOL WINAPI CryptMsgUpdate(HCRYPTMSG hCryptMsg, const BYTE *pbData, 3594 DWORD cbData, BOOL fFinal) 3595 { 3596 CryptMsgBase *msg = hCryptMsg; 3597 3598 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal); 3599 3600 return msg->update(hCryptMsg, pbData, cbData, fFinal); 3601 } 3602 3603 BOOL WINAPI CryptMsgGetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 3604 DWORD dwIndex, void *pvData, DWORD *pcbData) 3605 { 3606 CryptMsgBase *msg = hCryptMsg; 3607 3608 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex, 3609 pvData, pcbData); 3610 return msg->get_param(hCryptMsg, dwParamType, dwIndex, pvData, pcbData); 3611 } 3612 3613 BOOL WINAPI CryptMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags, 3614 DWORD dwCtrlType, const void *pvCtrlPara) 3615 { 3616 CryptMsgBase *msg = hCryptMsg; 3617 3618 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg, dwFlags, dwCtrlType, 3619 pvCtrlPara); 3620 return msg->control(hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara); 3621 } 3622 3623 static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg, 3624 DWORD dwSignerIndex) 3625 { 3626 CERT_INFO *certInfo = NULL; 3627 DWORD size; 3628 3629 if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL, 3630 &size)) 3631 { 3632 certInfo = CryptMemAlloc(size); 3633 if (certInfo) 3634 { 3635 if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, 3636 dwSignerIndex, certInfo, &size)) 3637 { 3638 CryptMemFree(certInfo); 3639 certInfo = NULL; 3640 } 3641 } 3642 } 3643 return certInfo; 3644 } 3645 3646 BOOL WINAPI CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg, DWORD cSignerStore, 3647 HCERTSTORE *rghSignerStore, DWORD dwFlags, PCCERT_CONTEXT *ppSigner, 3648 DWORD *pdwSignerIndex) 3649 { 3650 HCERTSTORE store; 3651 DWORD i, signerIndex = 0; 3652 PCCERT_CONTEXT signerCert = NULL; 3653 BOOL ret = FALSE; 3654 3655 TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg, cSignerStore, 3656 rghSignerStore, dwFlags, ppSigner, pdwSignerIndex); 3657 3658 /* Clear output parameters */ 3659 if (ppSigner) 3660 *ppSigner = NULL; 3661 if (pdwSignerIndex && !(dwFlags & CMSG_USE_SIGNER_INDEX_FLAG)) 3662 *pdwSignerIndex = 0; 3663 3664 /* Create store to search for signer certificates */ 3665 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 3666 CERT_STORE_CREATE_NEW_FLAG, NULL); 3667 if (!(dwFlags & CMSG_TRUSTED_SIGNER_FLAG)) 3668 { 3669 HCERTSTORE msgStore = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, 3670 hCryptMsg); 3671 3672 CertAddStoreToCollection(store, msgStore, 0, 0); 3673 CertCloseStore(msgStore, 0); 3674 } 3675 for (i = 0; i < cSignerStore; i++) 3676 CertAddStoreToCollection(store, rghSignerStore[i], 0, 0); 3677 3678 /* Find signer cert */ 3679 if (dwFlags & CMSG_USE_SIGNER_INDEX_FLAG) 3680 { 3681 CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg, 3682 *pdwSignerIndex); 3683 3684 if (signer) 3685 { 3686 signerIndex = *pdwSignerIndex; 3687 signerCert = CertFindCertificateInStore(store, X509_ASN_ENCODING, 3688 0, CERT_FIND_SUBJECT_CERT, signer, NULL); 3689 CryptMemFree(signer); 3690 } 3691 } 3692 else 3693 { 3694 DWORD count, size = sizeof(count); 3695 3696 if (CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_COUNT_PARAM, 0, &count, 3697 &size)) 3698 { 3699 for (i = 0; !signerCert && i < count; i++) 3700 { 3701 CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg, 3702 i); 3703 3704 if (signer) 3705 { 3706 signerCert = CertFindCertificateInStore(store, 3707 X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, signer, 3708 NULL); 3709 if (signerCert) 3710 signerIndex = i; 3711 CryptMemFree(signer); 3712 } 3713 } 3714 } 3715 if (!signerCert) 3716 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER); 3717 } 3718 if (signerCert) 3719 { 3720 if (!(dwFlags & CMSG_SIGNER_ONLY_FLAG)) 3721 ret = CryptMsgControl(hCryptMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE, 3722 signerCert->pCertInfo); 3723 else 3724 ret = TRUE; 3725 if (ret) 3726 { 3727 if (ppSigner) 3728 *ppSigner = CertDuplicateCertificateContext(signerCert); 3729 if (pdwSignerIndex) 3730 *pdwSignerIndex = signerIndex; 3731 } 3732 CertFreeCertificateContext(signerCert); 3733 } 3734 3735 CertCloseStore(store, 0); 3736 return ret; 3737 } 3738 3739 BOOL WINAPI CryptMsgVerifyCountersignatureEncoded(HCRYPTPROV_LEGACY hCryptProv, 3740 DWORD dwEncodingType, BYTE *pbSignerInfo, DWORD cbSignerInfo, 3741 PBYTE pbSignerInfoCountersignature, DWORD cbSignerInfoCountersignature, 3742 CERT_INFO *pciCountersigner) 3743 { 3744 FIXME("(%08lx, %08x, %p, %d, %p, %d, %p): stub\n", hCryptProv, 3745 dwEncodingType, pbSignerInfo, cbSignerInfo, pbSignerInfoCountersignature, 3746 cbSignerInfoCountersignature, pciCountersigner); 3747 return FALSE; 3748 } 3749 3750 BOOL WINAPI CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv, 3751 DWORD dwEncodingType, PBYTE pbSignerInfo, DWORD cbSignerInfo, 3752 PBYTE pbSignerInfoCountersignature, DWORD cbSignerInfoCountersignature, 3753 DWORD dwSignerType, void *pvSigner, DWORD dwFlags, void *pvReserved) 3754 { 3755 FIXME("(%08lx, %08x, %p, %d, %p, %d, %d, %p, %08x, %p): stub\n", hCryptProv, 3756 dwEncodingType, pbSignerInfo, cbSignerInfo, pbSignerInfoCountersignature, 3757 cbSignerInfoCountersignature, dwSignerType, pvSigner, dwFlags, pvReserved); 3758 return FALSE; 3759 } 3760 3761 BOOL WINAPI CryptMsgEncodeAndSignCTL(DWORD dwMsgEncodingType, 3762 PCTL_INFO pCtlInfo, PCMSG_SIGNED_ENCODE_INFO pSignInfo, DWORD dwFlags, 3763 BYTE *pbEncoded, DWORD *pcbEncoded) 3764 { 3765 BOOL ret; 3766 BYTE *pbCtlContent; 3767 DWORD cbCtlContent; 3768 3769 TRACE("(%08x, %p, %p, %08x, %p, %p)\n", dwMsgEncodingType, pCtlInfo, 3770 pSignInfo, dwFlags, pbEncoded, pcbEncoded); 3771 3772 if (dwFlags) 3773 { 3774 FIXME("unimplemented for flags %08x\n", dwFlags); 3775 return FALSE; 3776 } 3777 if ((ret = CryptEncodeObjectEx(dwMsgEncodingType, PKCS_CTL, pCtlInfo, 3778 CRYPT_ENCODE_ALLOC_FLAG, NULL, &pbCtlContent, &cbCtlContent))) 3779 { 3780 ret = CryptMsgSignCTL(dwMsgEncodingType, pbCtlContent, cbCtlContent, 3781 pSignInfo, dwFlags, pbEncoded, pcbEncoded); 3782 LocalFree(pbCtlContent); 3783 } 3784 return ret; 3785 } 3786 3787 BOOL WINAPI CryptMsgSignCTL(DWORD dwMsgEncodingType, BYTE *pbCtlContent, 3788 DWORD cbCtlContent, PCMSG_SIGNED_ENCODE_INFO pSignInfo, DWORD dwFlags, 3789 BYTE *pbEncoded, DWORD *pcbEncoded) 3790 { 3791 static char oid_ctl[] = szOID_CTL; 3792 BOOL ret; 3793 HCRYPTMSG msg; 3794 3795 TRACE("(%08x, %p, %d, %p, %08x, %p, %p)\n", dwMsgEncodingType, 3796 pbCtlContent, cbCtlContent, pSignInfo, dwFlags, pbEncoded, pcbEncoded); 3797 3798 if (dwFlags) 3799 { 3800 FIXME("unimplemented for flags %08x\n", dwFlags); 3801 return FALSE; 3802 } 3803 msg = CryptMsgOpenToEncode(dwMsgEncodingType, 0, CMSG_SIGNED, pSignInfo, 3804 oid_ctl, NULL); 3805 if (msg) 3806 { 3807 ret = CryptMsgUpdate(msg, pbCtlContent, cbCtlContent, TRUE); 3808 if (ret) 3809 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbEncoded, 3810 pcbEncoded); 3811 CryptMsgClose(msg); 3812 } 3813 else 3814 ret = FALSE; 3815 return ret; 3816 } 3817