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