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