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