Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmsg.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2007 Juan Lang 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include "config.h" 00020 #include "wine/port.h" 00021 00022 #include <stdarg.h> 00023 #define NONAMELESSUNION 00024 #include "windef.h" 00025 #include "winbase.h" 00026 #include "wincrypt.h" 00027 #include "snmp.h" 00028 00029 #include "wine/debug.h" 00030 #include "wine/exception.h" 00031 #include "crypt32_private.h" 00032 00033 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 00034 00035 /* Called when a message's ref count reaches zero. Free any message-specific 00036 * data here. 00037 */ 00038 typedef void (*CryptMsgCloseFunc)(HCRYPTMSG msg); 00039 00040 typedef BOOL (*CryptMsgGetParamFunc)(HCRYPTMSG hCryptMsg, DWORD dwParamType, 00041 DWORD dwIndex, void *pvData, DWORD *pcbData); 00042 00043 typedef BOOL (*CryptMsgUpdateFunc)(HCRYPTMSG hCryptMsg, const BYTE *pbData, 00044 DWORD cbData, BOOL fFinal); 00045 00046 typedef BOOL (*CryptMsgControlFunc)(HCRYPTMSG hCryptMsg, DWORD dwFlags, 00047 DWORD dwCtrlType, const void *pvCtrlPara); 00048 00049 static BOOL CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags, 00050 DWORD dwCtrlType, const void *pvCtrlPara) 00051 { 00052 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara); 00053 SetLastError(E_INVALIDARG); 00054 return FALSE; 00055 } 00056 00057 typedef enum _CryptMsgState { 00058 MsgStateInit, 00059 MsgStateUpdated, 00060 MsgStateDataFinalized, 00061 MsgStateFinalized 00062 } CryptMsgState; 00063 00064 typedef struct _CryptMsgBase 00065 { 00066 LONG ref; 00067 DWORD open_flags; 00068 BOOL streamed; 00069 CMSG_STREAM_INFO stream_info; 00070 CryptMsgState state; 00071 CryptMsgCloseFunc close; 00072 CryptMsgUpdateFunc update; 00073 CryptMsgGetParamFunc get_param; 00074 CryptMsgControlFunc control; 00075 } CryptMsgBase; 00076 00077 static inline void CryptMsgBase_Init(CryptMsgBase *msg, DWORD dwFlags, 00078 PCMSG_STREAM_INFO pStreamInfo, CryptMsgCloseFunc close, 00079 CryptMsgGetParamFunc get_param, CryptMsgUpdateFunc update, 00080 CryptMsgControlFunc control) 00081 { 00082 msg->ref = 1; 00083 msg->open_flags = dwFlags; 00084 if (pStreamInfo) 00085 { 00086 msg->streamed = TRUE; 00087 msg->stream_info = *pStreamInfo; 00088 } 00089 else 00090 { 00091 msg->streamed = FALSE; 00092 memset(&msg->stream_info, 0, sizeof(msg->stream_info)); 00093 } 00094 msg->close = close; 00095 msg->get_param = get_param; 00096 msg->update = update; 00097 msg->control = control; 00098 msg->state = MsgStateInit; 00099 } 00100 00101 typedef struct _CDataEncodeMsg 00102 { 00103 CryptMsgBase base; 00104 DWORD bare_content_len; 00105 LPBYTE bare_content; 00106 } CDataEncodeMsg; 00107 00108 static const BYTE empty_data_content[] = { 0x04,0x00 }; 00109 00110 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg) 00111 { 00112 CDataEncodeMsg *msg = hCryptMsg; 00113 00114 if (msg->bare_content != empty_data_content) 00115 LocalFree(msg->bare_content); 00116 } 00117 00118 static BOOL WINAPI CRYPT_EncodeContentLength(DWORD dwCertEncodingType, 00119 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00120 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00121 { 00122 DWORD dataLen = *(DWORD *)pvStructInfo; 00123 DWORD lenBytes; 00124 BOOL ret = TRUE; 00125 00126 /* Trick: report bytes needed based on total message length, even though 00127 * the message isn't available yet. The caller will use the length 00128 * reported here to encode its length. 00129 */ 00130 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 00131 if (!pbEncoded) 00132 *pcbEncoded = 1 + lenBytes + dataLen; 00133 else 00134 { 00135 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 00136 pcbEncoded, 1 + lenBytes))) 00137 { 00138 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00139 pbEncoded = *(BYTE **)pbEncoded; 00140 *pbEncoded++ = ASN_OCTETSTRING; 00141 CRYPT_EncodeLen(dataLen, pbEncoded, 00142 &lenBytes); 00143 } 00144 } 00145 return ret; 00146 } 00147 00148 static BOOL CRYPT_EncodeDataContentInfoHeader(const CDataEncodeMsg *msg, 00149 CRYPT_DATA_BLOB *header) 00150 { 00151 BOOL ret; 00152 00153 if (msg->base.streamed && msg->base.stream_info.cbContent == 0xffffffff) 00154 { 00155 static const BYTE headerValue[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48, 00156 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 }; 00157 00158 header->pbData = LocalAlloc(0, sizeof(headerValue)); 00159 if (header->pbData) 00160 { 00161 header->cbData = sizeof(headerValue); 00162 memcpy(header->pbData, headerValue, sizeof(headerValue)); 00163 ret = TRUE; 00164 } 00165 else 00166 ret = FALSE; 00167 } 00168 else 00169 { 00170 struct AsnConstructedItem constructed = { 0, 00171 &msg->base.stream_info.cbContent, CRYPT_EncodeContentLength }; 00172 struct AsnEncodeSequenceItem items[2] = { 00173 { szOID_RSA_data, CRYPT_AsnEncodeOid, 0 }, 00174 { &constructed, CRYPT_AsnEncodeConstructed, 0 }, 00175 }; 00176 00177 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 00178 sizeof(items) / sizeof(items[0]), CRYPT_ENCODE_ALLOC_FLAG, NULL, 00179 (LPBYTE)&header->pbData, &header->cbData); 00180 if (ret) 00181 { 00182 /* Trick: subtract the content length from the reported length, 00183 * as the actual content hasn't come yet. 00184 */ 00185 header->cbData -= msg->base.stream_info.cbContent; 00186 } 00187 } 00188 return ret; 00189 } 00190 00191 static BOOL CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 00192 DWORD cbData, BOOL fFinal) 00193 { 00194 CDataEncodeMsg *msg = hCryptMsg; 00195 BOOL ret = FALSE; 00196 00197 if (msg->base.state == MsgStateFinalized) 00198 SetLastError(CRYPT_E_MSG_ERROR); 00199 else if (msg->base.streamed) 00200 { 00201 __TRY 00202 { 00203 if (msg->base.state != MsgStateUpdated) 00204 { 00205 CRYPT_DATA_BLOB header; 00206 00207 ret = CRYPT_EncodeDataContentInfoHeader(msg, &header); 00208 if (ret) 00209 { 00210 ret = msg->base.stream_info.pfnStreamOutput( 00211 msg->base.stream_info.pvArg, header.pbData, header.cbData, 00212 FALSE); 00213 LocalFree(header.pbData); 00214 } 00215 } 00216 /* Curiously, every indefinite-length streamed update appears to 00217 * get its own tag and length, regardless of fFinal. 00218 */ 00219 if (msg->base.stream_info.cbContent == 0xffffffff) 00220 { 00221 BYTE *header; 00222 DWORD headerLen; 00223 00224 ret = CRYPT_EncodeContentLength(X509_ASN_ENCODING, NULL, 00225 &cbData, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&header, 00226 &headerLen); 00227 if (ret) 00228 { 00229 ret = msg->base.stream_info.pfnStreamOutput( 00230 msg->base.stream_info.pvArg, header, headerLen, 00231 FALSE); 00232 LocalFree(header); 00233 } 00234 } 00235 if (!fFinal) 00236 { 00237 ret = msg->base.stream_info.pfnStreamOutput( 00238 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData, 00239 FALSE); 00240 msg->base.state = MsgStateUpdated; 00241 } 00242 else 00243 { 00244 msg->base.state = MsgStateFinalized; 00245 if (msg->base.stream_info.cbContent == 0xffffffff) 00246 { 00247 BYTE indefinite_trailer[6] = { 0 }; 00248 00249 ret = msg->base.stream_info.pfnStreamOutput( 00250 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData, 00251 FALSE); 00252 if (ret) 00253 ret = msg->base.stream_info.pfnStreamOutput( 00254 msg->base.stream_info.pvArg, indefinite_trailer, 00255 sizeof(indefinite_trailer), TRUE); 00256 } 00257 else 00258 ret = msg->base.stream_info.pfnStreamOutput( 00259 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData, TRUE); 00260 } 00261 } 00262 __EXCEPT_PAGE_FAULT 00263 { 00264 SetLastError(STATUS_ACCESS_VIOLATION); 00265 ret = FALSE; 00266 } 00267 __ENDTRY; 00268 } 00269 else 00270 { 00271 if (!fFinal) 00272 { 00273 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 00274 SetLastError(E_INVALIDARG); 00275 else 00276 SetLastError(CRYPT_E_MSG_ERROR); 00277 } 00278 else 00279 { 00280 CRYPT_DATA_BLOB blob = { cbData, (LPBYTE)pbData }; 00281 00282 msg->base.state = MsgStateFinalized; 00283 /* non-streamed data messages don't allow non-final updates, 00284 * don't bother checking whether data already exist, they can't. 00285 */ 00286 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, 00287 &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL, &msg->bare_content, 00288 &msg->bare_content_len); 00289 } 00290 } 00291 return ret; 00292 } 00293 00294 static BOOL CRYPT_CopyParam(void *pvData, DWORD *pcbData, const void *src, 00295 DWORD len) 00296 { 00297 BOOL ret = TRUE; 00298 00299 if (!pvData) 00300 *pcbData = len; 00301 else if (*pcbData < len) 00302 { 00303 *pcbData = len; 00304 SetLastError(ERROR_MORE_DATA); 00305 ret = FALSE; 00306 } 00307 else 00308 { 00309 *pcbData = len; 00310 memcpy(pvData, src, len); 00311 } 00312 return ret; 00313 } 00314 00315 static BOOL CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 00316 DWORD dwIndex, void *pvData, DWORD *pcbData) 00317 { 00318 CDataEncodeMsg *msg = hCryptMsg; 00319 BOOL ret = FALSE; 00320 00321 switch (dwParamType) 00322 { 00323 case CMSG_CONTENT_PARAM: 00324 if (msg->base.streamed) 00325 SetLastError(E_INVALIDARG); 00326 else 00327 { 00328 CRYPT_CONTENT_INFO info; 00329 char rsa_data[] = "1.2.840.113549.1.7.1"; 00330 00331 info.pszObjId = rsa_data; 00332 info.Content.cbData = msg->bare_content_len; 00333 info.Content.pbData = msg->bare_content; 00334 ret = CryptEncodeObject(X509_ASN_ENCODING, PKCS_CONTENT_INFO, &info, 00335 pvData, pcbData); 00336 } 00337 break; 00338 case CMSG_BARE_CONTENT_PARAM: 00339 if (msg->base.streamed) 00340 SetLastError(E_INVALIDARG); 00341 else 00342 ret = CRYPT_CopyParam(pvData, pcbData, msg->bare_content, 00343 msg->bare_content_len); 00344 break; 00345 default: 00346 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 00347 } 00348 return ret; 00349 } 00350 00351 static HCRYPTMSG CDataEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo, 00352 LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo) 00353 { 00354 CDataEncodeMsg *msg; 00355 00356 if (pvMsgEncodeInfo) 00357 { 00358 SetLastError(E_INVALIDARG); 00359 return NULL; 00360 } 00361 msg = CryptMemAlloc(sizeof(CDataEncodeMsg)); 00362 if (msg) 00363 { 00364 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 00365 CDataEncodeMsg_Close, CDataEncodeMsg_GetParam, CDataEncodeMsg_Update, 00366 CRYPT_DefaultMsgControl); 00367 msg->bare_content_len = sizeof(empty_data_content); 00368 msg->bare_content = (LPBYTE)empty_data_content; 00369 } 00370 return msg; 00371 } 00372 00373 typedef struct _CHashEncodeMsg 00374 { 00375 CryptMsgBase base; 00376 HCRYPTPROV prov; 00377 HCRYPTHASH hash; 00378 CRYPT_DATA_BLOB data; 00379 } CHashEncodeMsg; 00380 00381 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg) 00382 { 00383 CHashEncodeMsg *msg = hCryptMsg; 00384 00385 CryptMemFree(msg->data.pbData); 00386 CryptDestroyHash(msg->hash); 00387 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) 00388 CryptReleaseContext(msg->prov, 0); 00389 } 00390 00391 static BOOL CRYPT_EncodePKCSDigestedData(CHashEncodeMsg *msg, void *pvData, 00392 DWORD *pcbData) 00393 { 00394 BOOL ret; 00395 ALG_ID algID; 00396 DWORD size = sizeof(algID); 00397 00398 ret = CryptGetHashParam(msg->hash, HP_ALGID, (BYTE *)&algID, &size, 0); 00399 if (ret) 00400 { 00401 CRYPT_DIGESTED_DATA digestedData = { 0 }; 00402 char oid_rsa_data[] = szOID_RSA_data; 00403 00404 digestedData.version = CMSG_HASHED_DATA_PKCS_1_5_VERSION; 00405 digestedData.DigestAlgorithm.pszObjId = (LPSTR)CertAlgIdToOID(algID); 00406 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */ 00407 /* Quirk: OID is only encoded messages if an update has happened */ 00408 if (msg->base.state != MsgStateInit) 00409 digestedData.ContentInfo.pszObjId = oid_rsa_data; 00410 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && msg->data.cbData) 00411 { 00412 ret = CRYPT_AsnEncodeOctets(0, NULL, &msg->data, 00413 CRYPT_ENCODE_ALLOC_FLAG, NULL, 00414 (LPBYTE)&digestedData.ContentInfo.Content.pbData, 00415 &digestedData.ContentInfo.Content.cbData); 00416 } 00417 if (msg->base.state == MsgStateFinalized) 00418 { 00419 size = sizeof(DWORD); 00420 ret = CryptGetHashParam(msg->hash, HP_HASHSIZE, 00421 (LPBYTE)&digestedData.hash.cbData, &size, 0); 00422 if (ret) 00423 { 00424 digestedData.hash.pbData = CryptMemAlloc( 00425 digestedData.hash.cbData); 00426 ret = CryptGetHashParam(msg->hash, HP_HASHVAL, 00427 digestedData.hash.pbData, &digestedData.hash.cbData, 0); 00428 } 00429 } 00430 if (ret) 00431 ret = CRYPT_AsnEncodePKCSDigestedData(&digestedData, pvData, 00432 pcbData); 00433 CryptMemFree(digestedData.hash.pbData); 00434 LocalFree(digestedData.ContentInfo.Content.pbData); 00435 } 00436 return ret; 00437 } 00438 00439 static BOOL CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 00440 DWORD dwIndex, void *pvData, DWORD *pcbData) 00441 { 00442 CHashEncodeMsg *msg = hCryptMsg; 00443 BOOL ret = FALSE; 00444 00445 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex, 00446 pvData, pcbData); 00447 00448 switch (dwParamType) 00449 { 00450 case CMSG_BARE_CONTENT_PARAM: 00451 if (msg->base.streamed) 00452 SetLastError(E_INVALIDARG); 00453 else 00454 ret = CRYPT_EncodePKCSDigestedData(msg, pvData, pcbData); 00455 break; 00456 case CMSG_CONTENT_PARAM: 00457 { 00458 CRYPT_CONTENT_INFO info; 00459 00460 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL, 00461 &info.Content.cbData); 00462 if (ret) 00463 { 00464 info.Content.pbData = CryptMemAlloc(info.Content.cbData); 00465 if (info.Content.pbData) 00466 { 00467 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, 00468 info.Content.pbData, &info.Content.cbData); 00469 if (ret) 00470 { 00471 char oid_rsa_hashed[] = szOID_RSA_hashedData; 00472 00473 info.pszObjId = oid_rsa_hashed; 00474 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, 00475 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData); 00476 } 00477 CryptMemFree(info.Content.pbData); 00478 } 00479 else 00480 ret = FALSE; 00481 } 00482 break; 00483 } 00484 case CMSG_COMPUTED_HASH_PARAM: 00485 ret = CryptGetHashParam(msg->hash, HP_HASHVAL, pvData, pcbData, 0); 00486 break; 00487 case CMSG_VERSION_PARAM: 00488 if (msg->base.state != MsgStateFinalized) 00489 SetLastError(CRYPT_E_MSG_ERROR); 00490 else 00491 { 00492 DWORD version = CMSG_HASHED_DATA_PKCS_1_5_VERSION; 00493 00494 /* Since the data are always encoded as octets, the version is 00495 * always 0 (see rfc3852, section 7) 00496 */ 00497 ret = CRYPT_CopyParam(pvData, pcbData, &version, sizeof(version)); 00498 } 00499 break; 00500 default: 00501 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 00502 } 00503 return ret; 00504 } 00505 00506 static BOOL CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 00507 DWORD cbData, BOOL fFinal) 00508 { 00509 CHashEncodeMsg *msg = hCryptMsg; 00510 BOOL ret = FALSE; 00511 00512 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal); 00513 00514 if (msg->base.state == MsgStateFinalized) 00515 SetLastError(CRYPT_E_MSG_ERROR); 00516 else if (msg->base.streamed || (msg->base.open_flags & CMSG_DETACHED_FLAG)) 00517 { 00518 /* Doesn't do much, as stream output is never called, and you 00519 * can't get the content. 00520 */ 00521 ret = CryptHashData(msg->hash, pbData, cbData, 0); 00522 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated; 00523 } 00524 else 00525 { 00526 if (!fFinal) 00527 SetLastError(CRYPT_E_MSG_ERROR); 00528 else 00529 { 00530 ret = CryptHashData(msg->hash, pbData, cbData, 0); 00531 if (ret) 00532 { 00533 msg->data.pbData = CryptMemAlloc(cbData); 00534 if (msg->data.pbData) 00535 { 00536 memcpy(msg->data.pbData + msg->data.cbData, pbData, cbData); 00537 msg->data.cbData += cbData; 00538 } 00539 else 00540 ret = FALSE; 00541 } 00542 msg->base.state = MsgStateFinalized; 00543 } 00544 } 00545 return ret; 00546 } 00547 00548 static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo, 00549 LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo) 00550 { 00551 CHashEncodeMsg *msg; 00552 const CMSG_HASHED_ENCODE_INFO *info = pvMsgEncodeInfo; 00553 HCRYPTPROV prov; 00554 ALG_ID algID; 00555 00556 if (info->cbSize != sizeof(CMSG_HASHED_ENCODE_INFO)) 00557 { 00558 SetLastError(E_INVALIDARG); 00559 return NULL; 00560 } 00561 if (!(algID = CertOIDToAlgId(info->HashAlgorithm.pszObjId))) 00562 { 00563 SetLastError(CRYPT_E_UNKNOWN_ALGO); 00564 return NULL; 00565 } 00566 if (info->hCryptProv) 00567 prov = info->hCryptProv; 00568 else 00569 { 00570 prov = CRYPT_GetDefaultProvider(); 00571 dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; 00572 } 00573 msg = CryptMemAlloc(sizeof(CHashEncodeMsg)); 00574 if (msg) 00575 { 00576 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 00577 CHashEncodeMsg_Close, CHashEncodeMsg_GetParam, CHashEncodeMsg_Update, 00578 CRYPT_DefaultMsgControl); 00579 msg->prov = prov; 00580 msg->data.cbData = 0; 00581 msg->data.pbData = NULL; 00582 if (!CryptCreateHash(prov, algID, 0, 0, &msg->hash)) 00583 { 00584 CryptMsgClose(msg); 00585 msg = NULL; 00586 } 00587 } 00588 return msg; 00589 } 00590 00591 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS 00592 { 00593 DWORD cbSize; 00594 PCERT_INFO pCertInfo; 00595 HCRYPTPROV hCryptProv; 00596 DWORD dwKeySpec; 00597 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; 00598 void *pvHashAuxInfo; 00599 DWORD cAuthAttr; 00600 PCRYPT_ATTRIBUTE rgAuthAttr; 00601 DWORD cUnauthAttr; 00602 PCRYPT_ATTRIBUTE rgUnauthAttr; 00603 CERT_ID SignerId; 00604 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; 00605 void *pvHashEncryptionAuxInfo; 00606 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS; 00607 00608 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS 00609 { 00610 DWORD cbSize; 00611 DWORD cSigners; 00612 PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners; 00613 DWORD cCertEncoded; 00614 PCERT_BLOB rgCertEncoded; 00615 DWORD cCrlEncoded; 00616 PCRL_BLOB rgCrlEncoded; 00617 DWORD cAttrCertEncoded; 00618 PCERT_BLOB rgAttrCertEncoded; 00619 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS; 00620 00621 static BOOL CRYPT_IsValidSigner(const CMSG_SIGNER_ENCODE_INFO_WITH_CMS *signer) 00622 { 00623 if (signer->cbSize != sizeof(CMSG_SIGNER_ENCODE_INFO) && 00624 signer->cbSize != sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS)) 00625 { 00626 SetLastError(E_INVALIDARG); 00627 return FALSE; 00628 } 00629 if (signer->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO)) 00630 { 00631 if (!signer->pCertInfo->SerialNumber.cbData) 00632 { 00633 SetLastError(E_INVALIDARG); 00634 return FALSE; 00635 } 00636 if (!signer->pCertInfo->Issuer.cbData) 00637 { 00638 SetLastError(E_INVALIDARG); 00639 return FALSE; 00640 } 00641 } 00642 else if (signer->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS)) 00643 { 00644 switch (signer->SignerId.dwIdChoice) 00645 { 00646 case 0: 00647 if (!signer->pCertInfo->SerialNumber.cbData) 00648 { 00649 SetLastError(E_INVALIDARG); 00650 return FALSE; 00651 } 00652 if (!signer->pCertInfo->Issuer.cbData) 00653 { 00654 SetLastError(E_INVALIDARG); 00655 return FALSE; 00656 } 00657 break; 00658 case CERT_ID_ISSUER_SERIAL_NUMBER: 00659 if (!signer->SignerId.u.IssuerSerialNumber.SerialNumber.cbData) 00660 { 00661 SetLastError(E_INVALIDARG); 00662 return FALSE; 00663 } 00664 if (!signer->SignerId.u.IssuerSerialNumber.Issuer.cbData) 00665 { 00666 SetLastError(E_INVALIDARG); 00667 return FALSE; 00668 } 00669 break; 00670 case CERT_ID_KEY_IDENTIFIER: 00671 if (!signer->SignerId.u.KeyId.cbData) 00672 { 00673 SetLastError(E_INVALIDARG); 00674 return FALSE; 00675 } 00676 break; 00677 default: 00678 SetLastError(E_INVALIDARG); 00679 } 00680 if (signer->HashEncryptionAlgorithm.pszObjId) 00681 { 00682 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n"); 00683 return FALSE; 00684 } 00685 } 00686 if (!signer->hCryptProv) 00687 { 00688 SetLastError(E_INVALIDARG); 00689 return FALSE; 00690 } 00691 if (!CertOIDToAlgId(signer->HashAlgorithm.pszObjId)) 00692 { 00693 SetLastError(CRYPT_E_UNKNOWN_ALGO); 00694 return FALSE; 00695 } 00696 return TRUE; 00697 } 00698 00699 static BOOL CRYPT_ConstructBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in) 00700 { 00701 BOOL ret = TRUE; 00702 00703 out->cbData = in->cbData; 00704 if (out->cbData) 00705 { 00706 out->pbData = CryptMemAlloc(out->cbData); 00707 if (out->pbData) 00708 memcpy(out->pbData, in->pbData, out->cbData); 00709 else 00710 ret = FALSE; 00711 } 00712 else 00713 out->pbData = NULL; 00714 return ret; 00715 } 00716 00717 static BOOL CRYPT_ConstructBlobArray(DWORD *outCBlobs, 00718 PCRYPT_DATA_BLOB *outPBlobs, DWORD cBlobs, const CRYPT_DATA_BLOB *pBlobs) 00719 { 00720 BOOL ret = TRUE; 00721 00722 *outCBlobs = cBlobs; 00723 if (cBlobs) 00724 { 00725 *outPBlobs = CryptMemAlloc(cBlobs * sizeof(CRYPT_DATA_BLOB)); 00726 if (*outPBlobs) 00727 { 00728 DWORD i; 00729 00730 memset(*outPBlobs, 0, cBlobs * sizeof(CRYPT_DATA_BLOB)); 00731 for (i = 0; ret && i < cBlobs; i++) 00732 ret = CRYPT_ConstructBlob(&(*outPBlobs)[i], &pBlobs[i]); 00733 } 00734 else 00735 ret = FALSE; 00736 } 00737 return ret; 00738 } 00739 00740 static void CRYPT_FreeBlobArray(DWORD cBlobs, PCRYPT_DATA_BLOB blobs) 00741 { 00742 DWORD i; 00743 00744 for (i = 0; i < cBlobs; i++) 00745 CryptMemFree(blobs[i].pbData); 00746 CryptMemFree(blobs); 00747 } 00748 00749 static BOOL CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE *out, 00750 const CRYPT_ATTRIBUTE *in) 00751 { 00752 BOOL ret; 00753 00754 out->pszObjId = CryptMemAlloc(strlen(in->pszObjId) + 1); 00755 if (out->pszObjId) 00756 { 00757 strcpy(out->pszObjId, in->pszObjId); 00758 ret = CRYPT_ConstructBlobArray(&out->cValue, &out->rgValue, 00759 in->cValue, in->rgValue); 00760 } 00761 else 00762 ret = FALSE; 00763 return ret; 00764 } 00765 00766 static BOOL CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES *out, 00767 const CRYPT_ATTRIBUTES *in) 00768 { 00769 BOOL ret = TRUE; 00770 00771 out->cAttr = in->cAttr; 00772 if (out->cAttr) 00773 { 00774 out->rgAttr = CryptMemAlloc(out->cAttr * sizeof(CRYPT_ATTRIBUTE)); 00775 if (out->rgAttr) 00776 { 00777 DWORD i; 00778 00779 memset(out->rgAttr, 0, out->cAttr * sizeof(CRYPT_ATTRIBUTE)); 00780 for (i = 0; ret && i < out->cAttr; i++) 00781 ret = CRYPT_ConstructAttribute(&out->rgAttr[i], &in->rgAttr[i]); 00782 } 00783 else 00784 ret = FALSE; 00785 } 00786 else 00787 out->rgAttr = NULL; 00788 return ret; 00789 } 00790 00791 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */ 00792 static BOOL CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO *info, 00793 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS *in) 00794 { 00795 BOOL ret; 00796 00797 if (in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO)) 00798 { 00799 info->dwVersion = CMSG_SIGNER_INFO_V1; 00800 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer, 00801 &in->pCertInfo->Issuer); 00802 if (ret) 00803 ret = CRYPT_ConstructBlob( 00804 &info->SignerId.u.IssuerSerialNumber.SerialNumber, 00805 &in->pCertInfo->SerialNumber); 00806 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 00807 info->HashEncryptionAlgorithm.pszObjId = 00808 in->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId; 00809 if (ret) 00810 ret = CRYPT_ConstructBlob(&info->HashEncryptionAlgorithm.Parameters, 00811 &in->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters); 00812 } 00813 else 00814 { 00815 const CRYPT_ALGORITHM_IDENTIFIER *pEncrAlg; 00816 00817 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS). 00818 * See CRYPT_IsValidSigner. 00819 */ 00820 if (!in->SignerId.dwIdChoice) 00821 { 00822 info->dwVersion = CMSG_SIGNER_INFO_V1; 00823 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer, 00824 &in->pCertInfo->Issuer); 00825 if (ret) 00826 ret = CRYPT_ConstructBlob( 00827 &info->SignerId.u.IssuerSerialNumber.SerialNumber, 00828 &in->pCertInfo->SerialNumber); 00829 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 00830 } 00831 else if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 00832 { 00833 info->dwVersion = CMSG_SIGNER_INFO_V1; 00834 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 00835 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer, 00836 &in->SignerId.u.IssuerSerialNumber.Issuer); 00837 if (ret) 00838 ret = CRYPT_ConstructBlob( 00839 &info->SignerId.u.IssuerSerialNumber.SerialNumber, 00840 &in->SignerId.u.IssuerSerialNumber.SerialNumber); 00841 } 00842 else 00843 { 00844 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */ 00845 info->dwVersion = CMSG_SIGNER_INFO_V3; 00846 info->SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER; 00847 ret = CRYPT_ConstructBlob(&info->SignerId.u.KeyId, 00848 &in->SignerId.u.KeyId); 00849 } 00850 pEncrAlg = in->HashEncryptionAlgorithm.pszObjId ? 00851 &in->HashEncryptionAlgorithm : 00852 &in->pCertInfo->SubjectPublicKeyInfo.Algorithm; 00853 info->HashEncryptionAlgorithm.pszObjId = pEncrAlg->pszObjId; 00854 if (ret) 00855 ret = CRYPT_ConstructBlob(&info->HashEncryptionAlgorithm.Parameters, 00856 &pEncrAlg->Parameters); 00857 } 00858 /* Assumption: algorithm IDs will point to static strings, not 00859 * stack-based ones, so copying the pointer values is safe. 00860 */ 00861 info->HashAlgorithm.pszObjId = in->HashAlgorithm.pszObjId; 00862 if (ret) 00863 ret = CRYPT_ConstructBlob(&info->HashAlgorithm.Parameters, 00864 &in->HashAlgorithm.Parameters); 00865 if (ret) 00866 ret = CRYPT_ConstructAttributes(&info->AuthAttrs, 00867 (CRYPT_ATTRIBUTES *)&in->cAuthAttr); 00868 if (ret) 00869 ret = CRYPT_ConstructAttributes(&info->UnauthAttrs, 00870 (CRYPT_ATTRIBUTES *)&in->cUnauthAttr); 00871 return ret; 00872 } 00873 00874 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO *info) 00875 { 00876 DWORD i, j; 00877 00878 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 00879 { 00880 CryptMemFree(info->SignerId.u.IssuerSerialNumber.Issuer.pbData); 00881 CryptMemFree(info->SignerId.u.IssuerSerialNumber.SerialNumber.pbData); 00882 } 00883 else 00884 CryptMemFree(info->SignerId.u.KeyId.pbData); 00885 CryptMemFree(info->HashAlgorithm.Parameters.pbData); 00886 CryptMemFree(info->HashEncryptionAlgorithm.Parameters.pbData); 00887 CryptMemFree(info->EncryptedHash.pbData); 00888 for (i = 0; i < info->AuthAttrs.cAttr; i++) 00889 { 00890 for (j = 0; j < info->AuthAttrs.rgAttr[i].cValue; j++) 00891 CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue[j].pbData); 00892 CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue); 00893 CryptMemFree(info->AuthAttrs.rgAttr[i].pszObjId); 00894 } 00895 CryptMemFree(info->AuthAttrs.rgAttr); 00896 for (i = 0; i < info->UnauthAttrs.cAttr; i++) 00897 { 00898 for (j = 0; j < info->UnauthAttrs.rgAttr[i].cValue; j++) 00899 CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue[j].pbData); 00900 CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue); 00901 CryptMemFree(info->UnauthAttrs.rgAttr[i].pszObjId); 00902 } 00903 CryptMemFree(info->UnauthAttrs.rgAttr); 00904 } 00905 00906 typedef struct _CSignerHandles 00907 { 00908 HCRYPTHASH contentHash; 00909 HCRYPTHASH authAttrHash; 00910 } CSignerHandles; 00911 00912 typedef struct _CSignedMsgData 00913 { 00914 CRYPT_SIGNED_INFO *info; 00915 DWORD cSignerHandle; 00916 CSignerHandles *signerHandles; 00917 } CSignedMsgData; 00918 00919 /* Constructs the signer handles for the signerIndex'th signer of msg_data. 00920 * Assumes signerIndex is a valid idnex, and that msg_data's info has already 00921 * been constructed. 00922 */ 00923 static BOOL CSignedMsgData_ConstructSignerHandles(CSignedMsgData *msg_data, 00924 DWORD signerIndex, HCRYPTPROV crypt_prov) 00925 { 00926 ALG_ID algID; 00927 BOOL ret; 00928 00929 algID = CertOIDToAlgId( 00930 msg_data->info->rgSignerInfo[signerIndex].HashAlgorithm.pszObjId); 00931 ret = CryptCreateHash(crypt_prov, algID, 0, 0, 00932 &msg_data->signerHandles->contentHash); 00933 if (ret && msg_data->info->rgSignerInfo[signerIndex].AuthAttrs.cAttr > 0) 00934 ret = CryptCreateHash(crypt_prov, algID, 0, 0, 00935 &msg_data->signerHandles->authAttrHash); 00936 return ret; 00937 } 00938 00939 /* Allocates a CSignedMsgData's handles. Assumes its info has already been 00940 * constructed. 00941 */ 00942 static BOOL CSignedMsgData_AllocateHandles(CSignedMsgData *msg_data) 00943 { 00944 BOOL ret = TRUE; 00945 00946 if (msg_data->info->cSignerInfo) 00947 { 00948 msg_data->signerHandles = 00949 CryptMemAlloc(msg_data->info->cSignerInfo * sizeof(CSignerHandles)); 00950 if (msg_data->signerHandles) 00951 { 00952 msg_data->cSignerHandle = msg_data->info->cSignerInfo; 00953 memset(msg_data->signerHandles, 0, 00954 msg_data->info->cSignerInfo * sizeof(CSignerHandles)); 00955 } 00956 else 00957 { 00958 msg_data->cSignerHandle = 0; 00959 ret = FALSE; 00960 } 00961 } 00962 else 00963 { 00964 msg_data->cSignerHandle = 0; 00965 msg_data->signerHandles = NULL; 00966 } 00967 return ret; 00968 } 00969 00970 static void CSignedMsgData_CloseHandles(CSignedMsgData *msg_data) 00971 { 00972 DWORD i; 00973 00974 for (i = 0; i < msg_data->cSignerHandle; i++) 00975 { 00976 if (msg_data->signerHandles[i].contentHash) 00977 CryptDestroyHash(msg_data->signerHandles[i].contentHash); 00978 if (msg_data->signerHandles[i].authAttrHash) 00979 CryptDestroyHash(msg_data->signerHandles[i].authAttrHash); 00980 } 00981 CryptMemFree(msg_data->signerHandles); 00982 msg_data->signerHandles = NULL; 00983 msg_data->cSignerHandle = 0; 00984 } 00985 00986 static BOOL CSignedMsgData_UpdateHash(CSignedMsgData *msg_data, 00987 const BYTE *pbData, DWORD cbData) 00988 { 00989 DWORD i; 00990 BOOL ret = TRUE; 00991 00992 for (i = 0; ret && i < msg_data->cSignerHandle; i++) 00993 ret = CryptHashData(msg_data->signerHandles[i].contentHash, pbData, 00994 cbData, 0); 00995 return ret; 00996 } 00997 00998 static BOOL CRYPT_AppendAttribute(CRYPT_ATTRIBUTES *out, 00999 const CRYPT_ATTRIBUTE *in) 01000 { 01001 BOOL ret = FALSE; 01002 01003 out->rgAttr = CryptMemRealloc(out->rgAttr, 01004 (out->cAttr + 1) * sizeof(CRYPT_ATTRIBUTE)); 01005 if (out->rgAttr) 01006 { 01007 ret = CRYPT_ConstructAttribute(&out->rgAttr[out->cAttr], in); 01008 if (ret) 01009 out->cAttr++; 01010 } 01011 return ret; 01012 } 01013 01014 static BOOL CSignedMsgData_AppendMessageDigestAttribute( 01015 CSignedMsgData *msg_data, DWORD signerIndex) 01016 { 01017 BOOL ret; 01018 DWORD size; 01019 CRYPT_HASH_BLOB hash = { 0, NULL }, encodedHash = { 0, NULL }; 01020 char messageDigest[] = szOID_RSA_messageDigest; 01021 CRYPT_ATTRIBUTE messageDigestAttr = { messageDigest, 1, &encodedHash }; 01022 01023 size = sizeof(DWORD); 01024 ret = CryptGetHashParam( 01025 msg_data->signerHandles[signerIndex].contentHash, HP_HASHSIZE, 01026 (LPBYTE)&hash.cbData, &size, 0); 01027 if (ret) 01028 { 01029 hash.pbData = CryptMemAlloc(hash.cbData); 01030 ret = CryptGetHashParam( 01031 msg_data->signerHandles[signerIndex].contentHash, HP_HASHVAL, 01032 hash.pbData, &hash.cbData, 0); 01033 if (ret) 01034 { 01035 ret = CRYPT_AsnEncodeOctets(0, NULL, &hash, CRYPT_ENCODE_ALLOC_FLAG, 01036 NULL, (LPBYTE)&encodedHash.pbData, &encodedHash.cbData); 01037 if (ret) 01038 { 01039 ret = CRYPT_AppendAttribute( 01040 &msg_data->info->rgSignerInfo[signerIndex].AuthAttrs, 01041 &messageDigestAttr); 01042 LocalFree(encodedHash.pbData); 01043 } 01044 } 01045 CryptMemFree(hash.pbData); 01046 } 01047 return ret; 01048 } 01049 01050 typedef enum { 01051 Sign, 01052 Verify 01053 } SignOrVerify; 01054 01055 static BOOL CSignedMsgData_UpdateAuthenticatedAttributes( 01056 CSignedMsgData *msg_data, SignOrVerify flag) 01057 { 01058 DWORD i; 01059 BOOL ret = TRUE; 01060 01061 TRACE("(%p)\n", msg_data); 01062 01063 for (i = 0; ret && i < msg_data->info->cSignerInfo; i++) 01064 { 01065 if (msg_data->info->rgSignerInfo[i].AuthAttrs.cAttr) 01066 { 01067 if (flag == Sign) 01068 { 01069 BYTE oid_rsa_data_encoded[] = { 0x06,0x09,0x2a,0x86,0x48,0x86, 01070 0xf7,0x0d,0x01,0x07,0x01 }; 01071 CRYPT_DATA_BLOB content = { sizeof(oid_rsa_data_encoded), 01072 oid_rsa_data_encoded }; 01073 char contentType[] = szOID_RSA_contentType; 01074 CRYPT_ATTRIBUTE contentTypeAttr = { contentType, 1, &content }; 01075 01076 /* FIXME: does this depend on inner OID? */ 01077 ret = CRYPT_AppendAttribute( 01078 &msg_data->info->rgSignerInfo[i].AuthAttrs, &contentTypeAttr); 01079 if (ret) 01080 ret = CSignedMsgData_AppendMessageDigestAttribute(msg_data, 01081 i); 01082 } 01083 if (ret) 01084 { 01085 LPBYTE encodedAttrs; 01086 DWORD size; 01087 01088 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, PKCS_ATTRIBUTES, 01089 &msg_data->info->rgSignerInfo[i].AuthAttrs, 01090 CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedAttrs, &size); 01091 if (ret) 01092 { 01093 ret = CryptHashData( 01094 msg_data->signerHandles[i].authAttrHash, encodedAttrs, 01095 size, 0); 01096 LocalFree(encodedAttrs); 01097 } 01098 } 01099 } 01100 } 01101 TRACE("returning %d\n", ret); 01102 return ret; 01103 } 01104 01105 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB *hash) 01106 { 01107 DWORD i; 01108 BYTE tmp; 01109 01110 for (i = 0; i < hash->cbData / 2; i++) 01111 { 01112 tmp = hash->pbData[hash->cbData - i - 1]; 01113 hash->pbData[hash->cbData - i - 1] = hash->pbData[i]; 01114 hash->pbData[i] = tmp; 01115 } 01116 } 01117 01118 static BOOL CSignedMsgData_Sign(CSignedMsgData *msg_data) 01119 { 01120 DWORD i; 01121 BOOL ret = TRUE; 01122 01123 TRACE("(%p)\n", msg_data); 01124 01125 for (i = 0; ret && i < msg_data->info->cSignerInfo; i++) 01126 { 01127 HCRYPTHASH hash; 01128 01129 if (msg_data->info->rgSignerInfo[i].AuthAttrs.cAttr) 01130 hash = msg_data->signerHandles[i].authAttrHash; 01131 else 01132 hash = msg_data->signerHandles[i].contentHash; 01133 ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0, NULL, 01134 &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData); 01135 if (ret) 01136 { 01137 msg_data->info->rgSignerInfo[i].EncryptedHash.pbData = 01138 CryptMemAlloc( 01139 msg_data->info->rgSignerInfo[i].EncryptedHash.cbData); 01140 if (msg_data->info->rgSignerInfo[i].EncryptedHash.pbData) 01141 { 01142 ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0, 01143 msg_data->info->rgSignerInfo[i].EncryptedHash.pbData, 01144 &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData); 01145 if (ret) 01146 CRYPT_ReverseBytes( 01147 &msg_data->info->rgSignerInfo[i].EncryptedHash); 01148 } 01149 else 01150 ret = FALSE; 01151 } 01152 } 01153 return ret; 01154 } 01155 01156 static BOOL CSignedMsgData_Update(CSignedMsgData *msg_data, 01157 const BYTE *pbData, DWORD cbData, BOOL fFinal, SignOrVerify flag) 01158 { 01159 BOOL ret = CSignedMsgData_UpdateHash(msg_data, pbData, cbData); 01160 01161 if (ret && fFinal) 01162 { 01163 ret = CSignedMsgData_UpdateAuthenticatedAttributes(msg_data, flag); 01164 if (ret && flag == Sign) 01165 ret = CSignedMsgData_Sign(msg_data); 01166 } 01167 return ret; 01168 } 01169 01170 typedef struct _CSignedEncodeMsg 01171 { 01172 CryptMsgBase base; 01173 LPSTR innerOID; 01174 CRYPT_DATA_BLOB data; 01175 CSignedMsgData msg_data; 01176 } CSignedEncodeMsg; 01177 01178 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg) 01179 { 01180 CSignedEncodeMsg *msg = hCryptMsg; 01181 DWORD i; 01182 01183 CryptMemFree(msg->innerOID); 01184 CryptMemFree(msg->data.pbData); 01185 CRYPT_FreeBlobArray(msg->msg_data.info->cCertEncoded, 01186 msg->msg_data.info->rgCertEncoded); 01187 CRYPT_FreeBlobArray(msg->msg_data.info->cCrlEncoded, 01188 msg->msg_data.info->rgCrlEncoded); 01189 for (i = 0; i < msg->msg_data.info->cSignerInfo; i++) 01190 CSignerInfo_Free(&msg->msg_data.info->rgSignerInfo[i]); 01191 CSignedMsgData_CloseHandles(&msg->msg_data); 01192 CryptMemFree(msg->msg_data.info->rgSignerInfo); 01193 CryptMemFree(msg->msg_data.info); 01194 } 01195 01196 static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 01197 DWORD dwIndex, void *pvData, DWORD *pcbData) 01198 { 01199 CSignedEncodeMsg *msg = hCryptMsg; 01200 BOOL ret = FALSE; 01201 01202 switch (dwParamType) 01203 { 01204 case CMSG_CONTENT_PARAM: 01205 { 01206 CRYPT_CONTENT_INFO info; 01207 01208 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL, 01209 &info.Content.cbData); 01210 if (ret) 01211 { 01212 info.Content.pbData = CryptMemAlloc(info.Content.cbData); 01213 if (info.Content.pbData) 01214 { 01215 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, 01216 info.Content.pbData, &info.Content.cbData); 01217 if (ret) 01218 { 01219 char oid_rsa_signed[] = szOID_RSA_signedData; 01220 01221 info.pszObjId = oid_rsa_signed; 01222 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, 01223 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData); 01224 } 01225 CryptMemFree(info.Content.pbData); 01226 } 01227 else 01228 ret = FALSE; 01229 } 01230 break; 01231 } 01232 case CMSG_BARE_CONTENT_PARAM: 01233 { 01234 CRYPT_SIGNED_INFO info; 01235 BOOL freeContent = FALSE; 01236 01237 info = *msg->msg_data.info; 01238 if (!msg->innerOID || !strcmp(msg->innerOID, szOID_RSA_data)) 01239 { 01240 char oid_rsa_data[] = szOID_RSA_data; 01241 01242 /* Quirk: OID is only encoded messages if an update has happened */ 01243 if (msg->base.state != MsgStateInit) 01244 info.content.pszObjId = oid_rsa_data; 01245 else 01246 info.content.pszObjId = NULL; 01247 if (msg->data.cbData) 01248 { 01249 CRYPT_DATA_BLOB blob = { msg->data.cbData, msg->data.pbData }; 01250 01251 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, 01252 &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL, 01253 &info.content.Content.pbData, &info.content.Content.cbData); 01254 freeContent = TRUE; 01255 } 01256 else 01257 { 01258 info.content.Content.cbData = 0; 01259 info.content.Content.pbData = NULL; 01260 ret = TRUE; 01261 } 01262 } 01263 else 01264 { 01265 info.content.pszObjId = msg->innerOID; 01266 info.content.Content.cbData = msg->data.cbData; 01267 info.content.Content.pbData = msg->data.pbData; 01268 ret = TRUE; 01269 } 01270 if (ret) 01271 { 01272 ret = CRYPT_AsnEncodeCMSSignedInfo(&info, pvData, pcbData); 01273 if (freeContent) 01274 LocalFree(info.content.Content.pbData); 01275 } 01276 break; 01277 } 01278 case CMSG_COMPUTED_HASH_PARAM: 01279 if (dwIndex >= msg->msg_data.cSignerHandle) 01280 SetLastError(CRYPT_E_INVALID_INDEX); 01281 else 01282 ret = CryptGetHashParam( 01283 msg->msg_data.signerHandles[dwIndex].contentHash, HP_HASHVAL, 01284 pvData, pcbData, 0); 01285 break; 01286 case CMSG_ENCODED_SIGNER: 01287 if (dwIndex >= msg->msg_data.info->cSignerInfo) 01288 SetLastError(CRYPT_E_INVALID_INDEX); 01289 else 01290 ret = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 01291 CMS_SIGNER_INFO, &msg->msg_data.info->rgSignerInfo[dwIndex], 0, 01292 NULL, pvData, pcbData); 01293 break; 01294 case CMSG_VERSION_PARAM: 01295 ret = CRYPT_CopyParam(pvData, pcbData, &msg->msg_data.info->version, 01296 sizeof(msg->msg_data.info->version)); 01297 break; 01298 default: 01299 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 01300 } 01301 return ret; 01302 } 01303 01304 static BOOL CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 01305 DWORD cbData, BOOL fFinal) 01306 { 01307 CSignedEncodeMsg *msg = hCryptMsg; 01308 BOOL ret = FALSE; 01309 01310 if (msg->base.state == MsgStateFinalized) 01311 SetLastError(CRYPT_E_MSG_ERROR); 01312 else if (msg->base.streamed || (msg->base.open_flags & CMSG_DETACHED_FLAG)) 01313 { 01314 ret = CSignedMsgData_Update(&msg->msg_data, pbData, cbData, fFinal, 01315 Sign); 01316 if (msg->base.streamed) 01317 FIXME("streamed partial stub\n"); 01318 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated; 01319 } 01320 else 01321 { 01322 if (!fFinal) 01323 SetLastError(CRYPT_E_MSG_ERROR); 01324 else 01325 { 01326 if (cbData) 01327 { 01328 msg->data.pbData = CryptMemAlloc(cbData); 01329 if (msg->data.pbData) 01330 { 01331 memcpy(msg->data.pbData, pbData, cbData); 01332 msg->data.cbData = cbData; 01333 ret = TRUE; 01334 } 01335 } 01336 else 01337 ret = TRUE; 01338 if (ret) 01339 ret = CSignedMsgData_Update(&msg->msg_data, pbData, cbData, 01340 fFinal, Sign); 01341 msg->base.state = MsgStateFinalized; 01342 } 01343 } 01344 return ret; 01345 } 01346 01347 static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags, 01348 const void *pvMsgEncodeInfo, LPCSTR pszInnerContentObjID, 01349 PCMSG_STREAM_INFO pStreamInfo) 01350 { 01351 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS *info = pvMsgEncodeInfo; 01352 DWORD i; 01353 CSignedEncodeMsg *msg; 01354 01355 if (info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO) && 01356 info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS)) 01357 { 01358 SetLastError(E_INVALIDARG); 01359 return NULL; 01360 } 01361 if (info->cbSize == sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS) && 01362 info->cAttrCertEncoded) 01363 { 01364 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n"); 01365 return NULL; 01366 } 01367 for (i = 0; i < info->cSigners; i++) 01368 if (!CRYPT_IsValidSigner(&info->rgSigners[i])) 01369 return NULL; 01370 msg = CryptMemAlloc(sizeof(CSignedEncodeMsg)); 01371 if (msg) 01372 { 01373 BOOL ret = TRUE; 01374 01375 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 01376 CSignedEncodeMsg_Close, CSignedEncodeMsg_GetParam, 01377 CSignedEncodeMsg_Update, CRYPT_DefaultMsgControl); 01378 if (pszInnerContentObjID) 01379 { 01380 msg->innerOID = CryptMemAlloc(strlen(pszInnerContentObjID) + 1); 01381 if (msg->innerOID) 01382 strcpy(msg->innerOID, pszInnerContentObjID); 01383 else 01384 ret = FALSE; 01385 } 01386 else 01387 msg->innerOID = NULL; 01388 msg->data.cbData = 0; 01389 msg->data.pbData = NULL; 01390 if (ret) 01391 msg->msg_data.info = CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO)); 01392 else 01393 msg->msg_data.info = NULL; 01394 if (msg->msg_data.info) 01395 { 01396 memset(msg->msg_data.info, 0, sizeof(CRYPT_SIGNED_INFO)); 01397 msg->msg_data.info->version = CMSG_SIGNED_DATA_V1; 01398 } 01399 else 01400 ret = FALSE; 01401 if (ret) 01402 { 01403 if (info->cSigners) 01404 { 01405 msg->msg_data.info->rgSignerInfo = 01406 CryptMemAlloc(info->cSigners * sizeof(CMSG_CMS_SIGNER_INFO)); 01407 if (msg->msg_data.info->rgSignerInfo) 01408 { 01409 msg->msg_data.info->cSignerInfo = info->cSigners; 01410 memset(msg->msg_data.info->rgSignerInfo, 0, 01411 msg->msg_data.info->cSignerInfo * 01412 sizeof(CMSG_CMS_SIGNER_INFO)); 01413 ret = CSignedMsgData_AllocateHandles(&msg->msg_data); 01414 for (i = 0; ret && i < msg->msg_data.info->cSignerInfo; i++) 01415 { 01416 if (info->rgSigners[i].SignerId.dwIdChoice == 01417 CERT_ID_KEY_IDENTIFIER) 01418 msg->msg_data.info->version = CMSG_SIGNED_DATA_V3; 01419 ret = CSignerInfo_Construct( 01420 &msg->msg_data.info->rgSignerInfo[i], 01421 &info->rgSigners[i]); 01422 if (ret) 01423 { 01424 ret = CSignedMsgData_ConstructSignerHandles( 01425 &msg->msg_data, i, info->rgSigners[i].hCryptProv); 01426 if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) 01427 CryptReleaseContext(info->rgSigners[i].hCryptProv, 01428 0); 01429 } 01430 } 01431 } 01432 else 01433 ret = FALSE; 01434 } 01435 else 01436 { 01437 msg->msg_data.info->cSignerInfo = 0; 01438 msg->msg_data.signerHandles = NULL; 01439 msg->msg_data.cSignerHandle = 0; 01440 } 01441 } 01442 if (ret) 01443 ret = CRYPT_ConstructBlobArray(&msg->msg_data.info->cCertEncoded, 01444 &msg->msg_data.info->rgCertEncoded, info->cCertEncoded, 01445 info->rgCertEncoded); 01446 if (ret) 01447 ret = CRYPT_ConstructBlobArray(&msg->msg_data.info->cCrlEncoded, 01448 &msg->msg_data.info->rgCrlEncoded, info->cCrlEncoded, 01449 info->rgCrlEncoded); 01450 if (!ret) 01451 { 01452 CSignedEncodeMsg_Close(msg); 01453 msg = NULL; 01454 } 01455 } 01456 return msg; 01457 } 01458 01459 typedef struct _CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS 01460 { 01461 DWORD cbSize; 01462 HCRYPTPROV_LEGACY hCryptProv; 01463 CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm; 01464 void *pvEncryptionAuxInfo; 01465 DWORD cRecipients; 01466 PCERT_INFO *rgpRecipientCert; 01467 PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients; 01468 DWORD cCertEncoded; 01469 PCERT_BLOB rgCertEncoded; 01470 DWORD cCrlEncoded; 01471 PCRL_BLOB rgCrlEncoded; 01472 DWORD cAttrCertEncoded; 01473 PCERT_BLOB rgAttrCertEncoded; 01474 DWORD cUnprotectedAttr; 01475 PCRYPT_ATTRIBUTE rgUnprotectedAttr; 01476 } CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS, *PCMSG_ENVELOPED_ENCODE_INFO_WITH_CMS; 01477 01478 typedef struct _CEnvelopedEncodeMsg 01479 { 01480 CryptMsgBase base; 01481 CRYPT_ALGORITHM_IDENTIFIER algo; 01482 HCRYPTPROV prov; 01483 HCRYPTKEY key; 01484 DWORD cRecipientInfo; 01485 CMSG_KEY_TRANS_RECIPIENT_INFO *recipientInfo; 01486 CRYPT_DATA_BLOB data; 01487 } CEnvelopedEncodeMsg; 01488 01489 static BOOL CRYPT_ConstructAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER *out, 01490 const CRYPT_ALGORITHM_IDENTIFIER *in) 01491 { 01492 out->pszObjId = CryptMemAlloc(strlen(in->pszObjId) + 1); 01493 if (out->pszObjId) 01494 { 01495 strcpy(out->pszObjId, in->pszObjId); 01496 return CRYPT_ConstructBlob(&out->Parameters, &in->Parameters); 01497 } 01498 else 01499 return FALSE; 01500 } 01501 01502 static BOOL CRYPT_ConstructBitBlob(CRYPT_BIT_BLOB *out, const CRYPT_BIT_BLOB *in) 01503 { 01504 out->cbData = in->cbData; 01505 out->cUnusedBits = in->cUnusedBits; 01506 if (out->cbData) 01507 { 01508 out->pbData = CryptMemAlloc(out->cbData); 01509 if (out->pbData) 01510 memcpy(out->pbData, in->pbData, out->cbData); 01511 else 01512 return FALSE; 01513 } 01514 else 01515 out->pbData = NULL; 01516 return TRUE; 01517 } 01518 01519 static BOOL CRYPT_GenKey(CMSG_CONTENT_ENCRYPT_INFO *info, ALG_ID algID) 01520 { 01521 static HCRYPTOIDFUNCSET set = NULL; 01522 PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY genKeyFunc = NULL; 01523 HCRYPTOIDFUNCADDR hFunc; 01524 BOOL ret; 01525 01526 if (!set) 01527 set = CryptInitOIDFunctionSet(CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC, 0); 01528 CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 01529 info->ContentEncryptionAlgorithm.pszObjId, 0, (void **)&genKeyFunc, &hFunc); 01530 if (genKeyFunc) 01531 { 01532 ret = genKeyFunc(info, 0, NULL); 01533 CryptFreeOIDFunctionAddress(hFunc, 0); 01534 } 01535 else 01536 ret = CryptGenKey(info->hCryptProv, algID, CRYPT_EXPORTABLE, 01537 &info->hContentEncryptKey); 01538 return ret; 01539 } 01540 01541 static BOOL WINAPI CRYPT_ExportKeyTrans( 01542 PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo, 01543 PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo, 01544 PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo, 01545 DWORD dwFlags, void *pvReserved) 01546 { 01547 CERT_PUBLIC_KEY_INFO keyInfo; 01548 HCRYPTKEY expKey; 01549 BOOL ret; 01550 01551 ret = CRYPT_ConstructAlgorithmId(&keyInfo.Algorithm, 01552 &pKeyTransEncodeInfo->KeyEncryptionAlgorithm); 01553 if (ret) 01554 CRYPT_ConstructBitBlob(&keyInfo.PublicKey, 01555 &pKeyTransEncodeInfo->RecipientPublicKey); 01556 01557 if (ret) 01558 ret = CryptImportPublicKeyInfo(pKeyTransEncodeInfo->hCryptProv, 01559 X509_ASN_ENCODING, &keyInfo, &expKey); 01560 if (ret) 01561 { 01562 DWORD size; 01563 01564 ret = CryptExportKey(pContentEncryptInfo->hContentEncryptKey, expKey, 01565 SIMPLEBLOB, 0, NULL, &size); 01566 if (ret) 01567 { 01568 BYTE *keyBlob; 01569 01570 keyBlob = CryptMemAlloc(size); 01571 if (keyBlob) 01572 { 01573 ret = CryptExportKey(pContentEncryptInfo->hContentEncryptKey, 01574 expKey, SIMPLEBLOB, 0, keyBlob, &size); 01575 if (ret) 01576 { 01577 DWORD head = sizeof(BLOBHEADER) + sizeof(ALG_ID); 01578 01579 pKeyTransEncryptInfo->EncryptedKey.pbData = 01580 CryptMemAlloc(size - head); 01581 if (pKeyTransEncryptInfo->EncryptedKey.pbData) 01582 { 01583 DWORD i, k = 0; 01584 01585 pKeyTransEncryptInfo->EncryptedKey.cbData = size - head; 01586 for (i = size - 1; i >= head; --i, ++k) 01587 pKeyTransEncryptInfo->EncryptedKey.pbData[k] = 01588 keyBlob[i]; 01589 } 01590 else 01591 ret = FALSE; 01592 } 01593 CryptMemFree(keyBlob); 01594 } 01595 else 01596 ret = FALSE; 01597 } 01598 CryptDestroyKey(expKey); 01599 } 01600 01601 CryptMemFree(keyInfo.PublicKey.pbData); 01602 CryptMemFree(keyInfo.Algorithm.pszObjId); 01603 CryptMemFree(keyInfo.Algorithm.Parameters.pbData); 01604 return ret; 01605 } 01606 01607 static BOOL CRYPT_ExportEncryptedKey(CMSG_CONTENT_ENCRYPT_INFO *info, DWORD i, 01608 CRYPT_DATA_BLOB *key) 01609 { 01610 static HCRYPTOIDFUNCSET set = NULL; 01611 PFN_CMSG_EXPORT_KEY_TRANS exportKeyFunc = NULL; 01612 HCRYPTOIDFUNCADDR hFunc = NULL; 01613 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *encodeInfo = 01614 info->rgCmsRecipients[i].u.pKeyTrans; 01615 CMSG_KEY_TRANS_ENCRYPT_INFO encryptInfo; 01616 BOOL ret; 01617 01618 memset(&encryptInfo, 0, sizeof(encryptInfo)); 01619 encryptInfo.cbSize = sizeof(encryptInfo); 01620 encryptInfo.dwRecipientIndex = i; 01621 ret = CRYPT_ConstructAlgorithmId(&encryptInfo.KeyEncryptionAlgorithm, 01622 &encodeInfo->KeyEncryptionAlgorithm); 01623 01624 if (!set) 01625 set = CryptInitOIDFunctionSet(CMSG_OID_EXPORT_KEY_TRANS_FUNC, 0); 01626 CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 01627 encryptInfo.KeyEncryptionAlgorithm.pszObjId, 0, (void **)&exportKeyFunc, 01628 &hFunc); 01629 if (!exportKeyFunc) 01630 exportKeyFunc = CRYPT_ExportKeyTrans; 01631 if (ret) 01632 { 01633 ret = exportKeyFunc(info, encodeInfo, &encryptInfo, 0, NULL); 01634 if (ret) 01635 { 01636 key->cbData = encryptInfo.EncryptedKey.cbData; 01637 key->pbData = encryptInfo.EncryptedKey.pbData; 01638 } 01639 } 01640 if (hFunc) 01641 CryptFreeOIDFunctionAddress(hFunc, 0); 01642 01643 CryptMemFree(encryptInfo.KeyEncryptionAlgorithm.pszObjId); 01644 CryptMemFree(encryptInfo.KeyEncryptionAlgorithm.Parameters.pbData); 01645 return ret; 01646 } 01647 01648 static LPVOID WINAPI mem_alloc(size_t size) 01649 { 01650 return HeapAlloc(GetProcessHeap(), 0, size); 01651 } 01652 01653 static VOID WINAPI mem_free(LPVOID pv) 01654 { 01655 HeapFree(GetProcessHeap(), 0, pv); 01656 } 01657 01658 01659 static BOOL CContentEncryptInfo_Construct(CMSG_CONTENT_ENCRYPT_INFO *info, 01660 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS *in, HCRYPTPROV prov) 01661 { 01662 BOOL ret; 01663 01664 info->cbSize = sizeof(CMSG_CONTENT_ENCRYPT_INFO); 01665 info->hCryptProv = prov; 01666 ret = CRYPT_ConstructAlgorithmId(&info->ContentEncryptionAlgorithm, 01667 &in->ContentEncryptionAlgorithm); 01668 info->pvEncryptionAuxInfo = in->pvEncryptionAuxInfo; 01669 info->cRecipients = in->cRecipients; 01670 if (ret) 01671 { 01672 info->rgCmsRecipients = CryptMemAlloc(in->cRecipients * 01673 sizeof(CMSG_RECIPIENT_ENCODE_INFO)); 01674 if (info->rgCmsRecipients) 01675 { 01676 DWORD i; 01677 01678 for (i = 0; ret && i < in->cRecipients; ++i) 01679 { 01680 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *encodeInfo; 01681 CERT_INFO *cert = in->rgpRecipientCert[i]; 01682 01683 info->rgCmsRecipients[i].dwRecipientChoice = 01684 CMSG_KEY_TRANS_RECIPIENT; 01685 encodeInfo = CryptMemAlloc(sizeof(*encodeInfo)); 01686 info->rgCmsRecipients[i].u.pKeyTrans = encodeInfo; 01687 if (encodeInfo) 01688 { 01689 encodeInfo->cbSize = sizeof(*encodeInfo); 01690 ret = CRYPT_ConstructAlgorithmId( 01691 &encodeInfo->KeyEncryptionAlgorithm, 01692 &cert->SubjectPublicKeyInfo.Algorithm); 01693 encodeInfo->pvKeyEncryptionAuxInfo = NULL; 01694 encodeInfo->hCryptProv = prov; 01695 if (ret) 01696 ret = CRYPT_ConstructBitBlob( 01697 &encodeInfo->RecipientPublicKey, 01698 &cert->SubjectPublicKeyInfo.PublicKey); 01699 if (ret) 01700 ret = CRYPT_ConstructBlob( 01701 &encodeInfo->RecipientId.u.IssuerSerialNumber.Issuer, 01702 &cert->Issuer); 01703 if (ret) 01704 ret = CRYPT_ConstructBlob( 01705 &encodeInfo->RecipientId.u.IssuerSerialNumber.SerialNumber, 01706 &cert->SerialNumber); 01707 } 01708 else 01709 ret = FALSE; 01710 } 01711 } 01712 else 01713 ret = FALSE; 01714 } 01715 info->pfnAlloc = mem_alloc; 01716 info->pfnFree = mem_free; 01717 return ret; 01718 } 01719 01720 static void CContentEncryptInfo_Free(CMSG_CONTENT_ENCRYPT_INFO *info) 01721 { 01722 CryptMemFree(info->ContentEncryptionAlgorithm.pszObjId); 01723 CryptMemFree(info->ContentEncryptionAlgorithm.Parameters.pbData); 01724 if (info->rgCmsRecipients) 01725 { 01726 DWORD i; 01727 01728 for (i = 0; i < info->cRecipients; ++i) 01729 { 01730 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *encodeInfo = 01731 info->rgCmsRecipients[i].u.pKeyTrans; 01732 01733 CryptMemFree(encodeInfo->KeyEncryptionAlgorithm.pszObjId); 01734 CryptMemFree(encodeInfo->KeyEncryptionAlgorithm.Parameters.pbData); 01735 CryptMemFree(encodeInfo->RecipientPublicKey.pbData); 01736 CryptMemFree( 01737 encodeInfo->RecipientId.u.IssuerSerialNumber.Issuer.pbData); 01738 CryptMemFree( 01739 encodeInfo->RecipientId.u.IssuerSerialNumber.SerialNumber.pbData); 01740 CryptMemFree(encodeInfo); 01741 } 01742 CryptMemFree(info->rgCmsRecipients); 01743 } 01744 } 01745 01746 static BOOL CRecipientInfo_Construct(CMSG_KEY_TRANS_RECIPIENT_INFO *info, 01747 const CERT_INFO *cert, CRYPT_DATA_BLOB *key) 01748 { 01749 BOOL ret; 01750 01751 info->dwVersion = CMSG_KEY_TRANS_PKCS_1_5_VERSION; 01752 info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 01753 ret = CRYPT_ConstructBlob(&info->RecipientId.u.IssuerSerialNumber.Issuer, 01754 &cert->Issuer); 01755 if (ret) 01756 ret = CRYPT_ConstructBlob( 01757 &info->RecipientId.u.IssuerSerialNumber.SerialNumber, 01758 &cert->SerialNumber); 01759 if (ret) 01760 ret = CRYPT_ConstructAlgorithmId(&info->KeyEncryptionAlgorithm, 01761 &cert->SubjectPublicKeyInfo.Algorithm); 01762 info->EncryptedKey.cbData = key->cbData; 01763 info->EncryptedKey.pbData = key->pbData; 01764 return ret; 01765 } 01766 01767 static void CRecipientInfo_Free(CMSG_KEY_TRANS_RECIPIENT_INFO *info) 01768 { 01769 CryptMemFree(info->RecipientId.u.IssuerSerialNumber.Issuer.pbData); 01770 CryptMemFree(info->RecipientId.u.IssuerSerialNumber.SerialNumber.pbData); 01771 CryptMemFree(info->KeyEncryptionAlgorithm.pszObjId); 01772 CryptMemFree(info->KeyEncryptionAlgorithm.Parameters.pbData); 01773 CryptMemFree(info->EncryptedKey.pbData); 01774 } 01775 01776 static void CEnvelopedEncodeMsg_Close(HCRYPTMSG hCryptMsg) 01777 { 01778 CEnvelopedEncodeMsg *msg = hCryptMsg; 01779 01780 CryptMemFree(msg->algo.pszObjId); 01781 CryptMemFree(msg->algo.Parameters.pbData); 01782 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) 01783 CryptReleaseContext(msg->prov, 0); 01784 CryptDestroyKey(msg->key); 01785 if (msg->recipientInfo) 01786 { 01787 DWORD i; 01788 01789 for (i = 0; i < msg->cRecipientInfo; ++i) 01790 CRecipientInfo_Free(&msg->recipientInfo[i]); 01791 CryptMemFree(msg->recipientInfo); 01792 } 01793 CryptMemFree(msg->data.pbData); 01794 } 01795 01796 static BOOL CEnvelopedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 01797 DWORD dwIndex, void *pvData, DWORD *pcbData) 01798 { 01799 CEnvelopedEncodeMsg *msg = hCryptMsg; 01800 BOOL ret = FALSE; 01801 01802 switch (dwParamType) 01803 { 01804 case CMSG_BARE_CONTENT_PARAM: 01805 if (msg->base.streamed) 01806 SetLastError(E_INVALIDARG); 01807 else 01808 { 01809 char oid_rsa_data[] = szOID_RSA_data; 01810 CRYPT_ENVELOPED_DATA envelopedData = { 01811 CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION, msg->cRecipientInfo, 01812 msg->recipientInfo, { oid_rsa_data, { 01813 msg->algo.pszObjId, 01814 { msg->algo.Parameters.cbData, msg->algo.Parameters.pbData } 01815 }, 01816 { msg->data.cbData, msg->data.pbData } 01817 } 01818 }; 01819 01820 ret = CRYPT_AsnEncodePKCSEnvelopedData(&envelopedData, pvData, 01821 pcbData); 01822 } 01823 break; 01824 case CMSG_CONTENT_PARAM: 01825 { 01826 CRYPT_CONTENT_INFO info; 01827 01828 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL, 01829 &info.Content.cbData); 01830 if (ret) 01831 { 01832 info.Content.pbData = CryptMemAlloc(info.Content.cbData); 01833 if (info.Content.pbData) 01834 { 01835 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, 01836 info.Content.pbData, &info.Content.cbData); 01837 if (ret) 01838 { 01839 char oid_rsa_enveloped[] = szOID_RSA_envelopedData; 01840 01841 info.pszObjId = oid_rsa_enveloped; 01842 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, 01843 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData); 01844 } 01845 CryptMemFree(info.Content.pbData); 01846 } 01847 else 01848 ret = FALSE; 01849 } 01850 break; 01851 } 01852 default: 01853 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 01854 } 01855 return ret; 01856 } 01857 01858 static BOOL CEnvelopedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 01859 DWORD cbData, BOOL fFinal) 01860 { 01861 CEnvelopedEncodeMsg *msg = hCryptMsg; 01862 BOOL ret = FALSE; 01863 01864 if (msg->base.state == MsgStateFinalized) 01865 SetLastError(CRYPT_E_MSG_ERROR); 01866 else if (msg->base.streamed) 01867 { 01868 FIXME("streamed stub\n"); 01869 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated; 01870 ret = TRUE; 01871 } 01872 else 01873 { 01874 if (!fFinal) 01875 { 01876 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 01877 SetLastError(E_INVALIDARG); 01878 else 01879 SetLastError(CRYPT_E_MSG_ERROR); 01880 } 01881 else 01882 { 01883 if (cbData) 01884 { 01885 DWORD dataLen = cbData; 01886 01887 msg->data.cbData = cbData; 01888 msg->data.pbData = CryptMemAlloc(cbData); 01889 if (msg->data.pbData) 01890 { 01891 memcpy(msg->data.pbData, pbData, cbData); 01892 ret = CryptEncrypt(msg->key, 0, TRUE, 0, msg->data.pbData, 01893 &dataLen, msg->data.cbData); 01894 msg->data.cbData = dataLen; 01895 if (dataLen > cbData) 01896 { 01897 msg->data.pbData = CryptMemRealloc(msg->data.pbData, 01898 dataLen); 01899 if (msg->data.pbData) 01900 { 01901 dataLen = cbData; 01902 ret = CryptEncrypt(msg->key, 0, TRUE, 0, 01903 msg->data.pbData, &dataLen, msg->data.cbData); 01904 } 01905 else 01906 ret = FALSE; 01907 } 01908 if (!ret) 01909 CryptMemFree(msg->data.pbData); 01910 } 01911 else 01912 ret = FALSE; 01913 if (!ret) 01914 { 01915 msg->data.cbData = 0; 01916 msg->data.pbData = NULL; 01917 } 01918 } 01919 else 01920 ret = TRUE; 01921 msg->base.state = MsgStateFinalized; 01922 } 01923 } 01924 return ret; 01925 } 01926 01927 static HCRYPTMSG CEnvelopedEncodeMsg_Open(DWORD dwFlags, 01928 const void *pvMsgEncodeInfo, LPCSTR pszInnerContentObjID, 01929 PCMSG_STREAM_INFO pStreamInfo) 01930 { 01931 CEnvelopedEncodeMsg *msg; 01932 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS *info = pvMsgEncodeInfo; 01933 HCRYPTPROV prov; 01934 ALG_ID algID; 01935 01936 if (info->cbSize != sizeof(CMSG_ENVELOPED_ENCODE_INFO) && 01937 info->cbSize != sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS)) 01938 { 01939 SetLastError(E_INVALIDARG); 01940 return NULL; 01941 } 01942 if (info->cbSize == sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS)) 01943 FIXME("CMS fields unsupported\n"); 01944 if (!(algID = CertOIDToAlgId(info->ContentEncryptionAlgorithm.pszObjId))) 01945 { 01946 SetLastError(CRYPT_E_UNKNOWN_ALGO); 01947 return NULL; 01948 } 01949 if (info->cRecipients && !info->rgpRecipientCert) 01950 { 01951 SetLastError(E_INVALIDARG); 01952 return NULL; 01953 } 01954 if (info->hCryptProv) 01955 prov = info->hCryptProv; 01956 else 01957 { 01958 prov = CRYPT_GetDefaultProvider(); 01959 dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; 01960 } 01961 msg = CryptMemAlloc(sizeof(CEnvelopedEncodeMsg)); 01962 if (msg) 01963 { 01964 CRYPT_DATA_BLOB encryptedKey = { 0, NULL }; 01965 CMSG_CONTENT_ENCRYPT_INFO encryptInfo; 01966 BOOL ret; 01967 DWORD i; 01968 01969 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 01970 CEnvelopedEncodeMsg_Close, CEnvelopedEncodeMsg_GetParam, 01971 CEnvelopedEncodeMsg_Update, CRYPT_DefaultMsgControl); 01972 ret = CRYPT_ConstructAlgorithmId(&msg->algo, 01973 &info->ContentEncryptionAlgorithm); 01974 msg->prov = prov; 01975 msg->data.cbData = 0; 01976 msg->data.pbData = NULL; 01977 msg->cRecipientInfo = info->cRecipients; 01978 msg->recipientInfo = CryptMemAlloc(info->cRecipients * 01979 sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO)); 01980 if (!msg->recipientInfo) 01981 ret = FALSE; 01982 memset(&encryptInfo, 0, sizeof(encryptInfo)); 01983 if (ret) 01984 { 01985 ret = CContentEncryptInfo_Construct(&encryptInfo, info, prov); 01986 if (ret) 01987 { 01988 ret = CRYPT_GenKey(&encryptInfo, algID); 01989 if (ret) 01990 msg->key = encryptInfo.hContentEncryptKey; 01991 } 01992 } 01993 for (i = 0; ret && i < msg->cRecipientInfo; ++i) 01994 { 01995 ret = CRYPT_ExportEncryptedKey(&encryptInfo, i, &encryptedKey); 01996 if (ret) 01997 ret = CRecipientInfo_Construct(&msg->recipientInfo[i], 01998 info->rgpRecipientCert[i], &encryptedKey); 01999 } 02000 CContentEncryptInfo_Free(&encryptInfo); 02001 if (!ret) 02002 { 02003 CryptMsgClose(msg); 02004 msg = NULL; 02005 } 02006 } 02007 if (!msg && (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)) 02008 CryptReleaseContext(prov, 0); 02009 return msg; 02010 } 02011 02012 HCRYPTMSG WINAPI CryptMsgOpenToEncode(DWORD dwMsgEncodingType, DWORD dwFlags, 02013 DWORD dwMsgType, const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID, 02014 PCMSG_STREAM_INFO pStreamInfo) 02015 { 02016 HCRYPTMSG msg = NULL; 02017 02018 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType, dwFlags, 02019 dwMsgType, pvMsgEncodeInfo, debugstr_a(pszInnerContentObjID), pStreamInfo); 02020 02021 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING) 02022 { 02023 SetLastError(E_INVALIDARG); 02024 return NULL; 02025 } 02026 switch (dwMsgType) 02027 { 02028 case CMSG_DATA: 02029 msg = CDataEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, 02030 pszInnerContentObjID, pStreamInfo); 02031 break; 02032 case CMSG_HASHED: 02033 msg = CHashEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, 02034 pszInnerContentObjID, pStreamInfo); 02035 break; 02036 case CMSG_SIGNED: 02037 msg = CSignedEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, 02038 pszInnerContentObjID, pStreamInfo); 02039 break; 02040 case CMSG_ENVELOPED: 02041 msg = CEnvelopedEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, 02042 pszInnerContentObjID, pStreamInfo); 02043 break; 02044 case CMSG_SIGNED_AND_ENVELOPED: 02045 case CMSG_ENCRYPTED: 02046 /* defined but invalid, fall through */ 02047 default: 02048 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 02049 } 02050 return msg; 02051 } 02052 02053 typedef struct _CEnvelopedDecodeMsg 02054 { 02055 CRYPT_ENVELOPED_DATA *data; 02056 HCRYPTPROV crypt_prov; 02057 CRYPT_DATA_BLOB content; 02058 BOOL decrypted; 02059 } CEnvelopedDecodeMsg; 02060 02061 typedef struct _CDecodeMsg 02062 { 02063 CryptMsgBase base; 02064 DWORD type; 02065 HCRYPTPROV crypt_prov; 02066 union { 02067 HCRYPTHASH hash; 02068 CSignedMsgData signed_data; 02069 CEnvelopedDecodeMsg enveloped_data; 02070 } u; 02071 CRYPT_DATA_BLOB msg_data; 02072 CRYPT_DATA_BLOB detached_data; 02073 PCONTEXT_PROPERTY_LIST properties; 02074 } CDecodeMsg; 02075 02076 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg) 02077 { 02078 CDecodeMsg *msg = hCryptMsg; 02079 02080 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) 02081 CryptReleaseContext(msg->crypt_prov, 0); 02082 switch (msg->type) 02083 { 02084 case CMSG_HASHED: 02085 if (msg->u.hash) 02086 CryptDestroyHash(msg->u.hash); 02087 break; 02088 case CMSG_ENVELOPED: 02089 if (msg->u.enveloped_data.crypt_prov) 02090 CryptReleaseContext(msg->u.enveloped_data.crypt_prov, 0); 02091 LocalFree(msg->u.enveloped_data.data); 02092 CryptMemFree(msg->u.enveloped_data.content.pbData); 02093 break; 02094 case CMSG_SIGNED: 02095 if (msg->u.signed_data.info) 02096 { 02097 LocalFree(msg->u.signed_data.info); 02098 CSignedMsgData_CloseHandles(&msg->u.signed_data); 02099 } 02100 break; 02101 } 02102 CryptMemFree(msg->msg_data.pbData); 02103 CryptMemFree(msg->detached_data.pbData); 02104 ContextPropertyList_Free(msg->properties); 02105 } 02106 02107 static BOOL CDecodeMsg_CopyData(CRYPT_DATA_BLOB *blob, const BYTE *pbData, 02108 DWORD cbData) 02109 { 02110 BOOL ret = TRUE; 02111 02112 if (cbData) 02113 { 02114 if (blob->cbData) 02115 blob->pbData = CryptMemRealloc(blob->pbData, 02116 blob->cbData + cbData); 02117 else 02118 blob->pbData = CryptMemAlloc(cbData); 02119 if (blob->pbData) 02120 { 02121 memcpy(blob->pbData + blob->cbData, pbData, cbData); 02122 blob->cbData += cbData; 02123 } 02124 else 02125 ret = FALSE; 02126 } 02127 return ret; 02128 } 02129 02130 static BOOL CDecodeMsg_DecodeDataContent(CDecodeMsg *msg, const CRYPT_DER_BLOB *blob) 02131 { 02132 BOOL ret; 02133 CRYPT_DATA_BLOB *data; 02134 DWORD size; 02135 02136 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, 02137 blob->pbData, blob->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &data, &size); 02138 if (ret) 02139 { 02140 ret = ContextPropertyList_SetProperty(msg->properties, 02141 CMSG_CONTENT_PARAM, data->pbData, data->cbData); 02142 LocalFree(data); 02143 } 02144 return ret; 02145 } 02146 02147 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg *msg, DWORD param, 02148 const CRYPT_ALGORITHM_IDENTIFIER *id) 02149 { 02150 static const BYTE nullParams[] = { ASN_NULL, 0 }; 02151 CRYPT_ALGORITHM_IDENTIFIER *copy; 02152 DWORD len = sizeof(CRYPT_ALGORITHM_IDENTIFIER); 02153 02154 /* Linearize algorithm id */ 02155 len += strlen(id->pszObjId) + 1; 02156 len += id->Parameters.cbData; 02157 copy = CryptMemAlloc(len); 02158 if (copy) 02159 { 02160 copy->pszObjId = 02161 (LPSTR)((BYTE *)copy + sizeof(CRYPT_ALGORITHM_IDENTIFIER)); 02162 strcpy(copy->pszObjId, id->pszObjId); 02163 copy->Parameters.pbData = (BYTE *)copy->pszObjId + strlen(id->pszObjId) 02164 + 1; 02165 /* Trick: omit NULL parameters */ 02166 if (id->Parameters.cbData == sizeof(nullParams) && 02167 !memcmp(id->Parameters.pbData, nullParams, sizeof(nullParams))) 02168 { 02169 copy->Parameters.cbData = 0; 02170 len -= sizeof(nullParams); 02171 } 02172 else 02173 copy->Parameters.cbData = id->Parameters.cbData; 02174 if (copy->Parameters.cbData) 02175 memcpy(copy->Parameters.pbData, id->Parameters.pbData, 02176 id->Parameters.cbData); 02177 ContextPropertyList_SetProperty(msg->properties, param, (BYTE *)copy, 02178 len); 02179 CryptMemFree(copy); 02180 } 02181 } 02182 02183 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER *id) 02184 { 02185 id->pszObjId = (LPSTR)((BYTE *)id + sizeof(CRYPT_ALGORITHM_IDENTIFIER)); 02186 id->Parameters.pbData = (BYTE *)id->pszObjId + strlen(id->pszObjId) + 1; 02187 } 02188 02189 static BOOL CDecodeMsg_DecodeHashedContent(CDecodeMsg *msg, 02190 const CRYPT_DER_BLOB *blob) 02191 { 02192 BOOL ret; 02193 CRYPT_DIGESTED_DATA *digestedData; 02194 DWORD size; 02195 02196 ret = CRYPT_AsnDecodePKCSDigestedData(blob->pbData, blob->cbData, 02197 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_DIGESTED_DATA *)&digestedData, 02198 &size); 02199 if (ret) 02200 { 02201 ContextPropertyList_SetProperty(msg->properties, CMSG_VERSION_PARAM, 02202 (const BYTE *)&digestedData->version, sizeof(digestedData->version)); 02203 CDecodeMsg_SaveAlgorithmID(msg, CMSG_HASH_ALGORITHM_PARAM, 02204 &digestedData->DigestAlgorithm); 02205 ContextPropertyList_SetProperty(msg->properties, 02206 CMSG_INNER_CONTENT_TYPE_PARAM, 02207 (const BYTE *)digestedData->ContentInfo.pszObjId, 02208 digestedData->ContentInfo.pszObjId ? 02209 strlen(digestedData->ContentInfo.pszObjId) + 1 : 0); 02210 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG)) 02211 { 02212 if (digestedData->ContentInfo.Content.cbData) 02213 CDecodeMsg_DecodeDataContent(msg, 02214 &digestedData->ContentInfo.Content); 02215 else 02216 ContextPropertyList_SetProperty(msg->properties, 02217 CMSG_CONTENT_PARAM, NULL, 0); 02218 } 02219 ContextPropertyList_SetProperty(msg->properties, CMSG_HASH_DATA_PARAM, 02220 digestedData->hash.pbData, digestedData->hash.cbData); 02221 LocalFree(digestedData); 02222 } 02223 return ret; 02224 } 02225 02226 static BOOL CDecodeMsg_DecodeEnvelopedContent(CDecodeMsg *msg, 02227 const CRYPT_DER_BLOB *blob) 02228 { 02229 BOOL ret; 02230 CRYPT_ENVELOPED_DATA *envelopedData; 02231 DWORD size; 02232 02233 ret = CRYPT_AsnDecodePKCSEnvelopedData(blob->pbData, blob->cbData, 02234 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_ENVELOPED_DATA *)&envelopedData, 02235 &size); 02236 if (ret) 02237 msg->u.enveloped_data.data = envelopedData; 02238 return ret; 02239 } 02240 02241 static BOOL CDecodeMsg_DecodeSignedContent(CDecodeMsg *msg, 02242 const CRYPT_DER_BLOB *blob) 02243 { 02244 BOOL ret; 02245 CRYPT_SIGNED_INFO *signedInfo; 02246 DWORD size; 02247 02248 ret = CRYPT_AsnDecodeCMSSignedInfo(blob->pbData, blob->cbData, 02249 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_SIGNED_INFO *)&signedInfo, 02250 &size); 02251 if (ret) 02252 msg->u.signed_data.info = signedInfo; 02253 return ret; 02254 } 02255 02256 /* Decodes the content in blob as the type given, and updates the value 02257 * (type, parameters, etc.) of msg based on what blob contains. 02258 * It doesn't just use msg's type, to allow a recursive call from an implicitly 02259 * typed message once the outer content info has been decoded. 02260 */ 02261 static BOOL CDecodeMsg_DecodeContent(CDecodeMsg *msg, const CRYPT_DER_BLOB *blob, 02262 DWORD type) 02263 { 02264 BOOL ret; 02265 02266 switch (type) 02267 { 02268 case CMSG_DATA: 02269 if ((ret = CDecodeMsg_DecodeDataContent(msg, blob))) 02270 msg->type = CMSG_DATA; 02271 break; 02272 case CMSG_HASHED: 02273 if ((ret = CDecodeMsg_DecodeHashedContent(msg, blob))) 02274 msg->type = CMSG_HASHED; 02275 break; 02276 case CMSG_ENVELOPED: 02277 if ((ret = CDecodeMsg_DecodeEnvelopedContent(msg, blob))) 02278 msg->type = CMSG_ENVELOPED; 02279 break; 02280 case CMSG_SIGNED: 02281 if ((ret = CDecodeMsg_DecodeSignedContent(msg, blob))) 02282 msg->type = CMSG_SIGNED; 02283 break; 02284 default: 02285 { 02286 CRYPT_CONTENT_INFO *info; 02287 DWORD size; 02288 02289 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, PKCS_CONTENT_INFO, 02290 msg->msg_data.pbData, msg->msg_data.cbData, CRYPT_DECODE_ALLOC_FLAG, 02291 NULL, &info, &size); 02292 if (ret) 02293 { 02294 if (!strcmp(info->pszObjId, szOID_RSA_data)) 02295 ret = CDecodeMsg_DecodeContent(msg, &info->Content, CMSG_DATA); 02296 else if (!strcmp(info->pszObjId, szOID_RSA_digestedData)) 02297 ret = CDecodeMsg_DecodeContent(msg, &info->Content, 02298 CMSG_HASHED); 02299 else if (!strcmp(info->pszObjId, szOID_RSA_envelopedData)) 02300 ret = CDecodeMsg_DecodeContent(msg, &info->Content, 02301 CMSG_ENVELOPED); 02302 else if (!strcmp(info->pszObjId, szOID_RSA_signedData)) 02303 ret = CDecodeMsg_DecodeContent(msg, &info->Content, 02304 CMSG_SIGNED); 02305 else 02306 { 02307 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 02308 ret = FALSE; 02309 } 02310 LocalFree(info); 02311 } 02312 } 02313 } 02314 return ret; 02315 } 02316 02317 static BOOL CDecodeMsg_FinalizeHashedContent(CDecodeMsg *msg, 02318 CRYPT_DER_BLOB *blob) 02319 { 02320 CRYPT_ALGORITHM_IDENTIFIER *hashAlgoID = NULL; 02321 DWORD size = 0; 02322 ALG_ID algID = 0; 02323 BOOL ret; 02324 02325 CryptMsgGetParam(msg, CMSG_HASH_ALGORITHM_PARAM, 0, NULL, &size); 02326 hashAlgoID = CryptMemAlloc(size); 02327 ret = CryptMsgGetParam(msg, CMSG_HASH_ALGORITHM_PARAM, 0, hashAlgoID, 02328 &size); 02329 if (ret) 02330 algID = CertOIDToAlgId(hashAlgoID->pszObjId); 02331 ret = CryptCreateHash(msg->crypt_prov, algID, 0, 0, &msg->u.hash); 02332 if (ret) 02333 { 02334 CRYPT_DATA_BLOB content; 02335 02336 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 02337 { 02338 /* Unlike for non-detached messages, the data were never stored as 02339 * the content param, but were saved in msg->detached_data instead. 02340 */ 02341 content.pbData = msg->detached_data.pbData; 02342 content.cbData = msg->detached_data.cbData; 02343 } 02344 else 02345 ret = ContextPropertyList_FindProperty(msg->properties, 02346 CMSG_CONTENT_PARAM, &content); 02347 if (ret) 02348 ret = CryptHashData(msg->u.hash, content.pbData, content.cbData, 0); 02349 } 02350 CryptMemFree(hashAlgoID); 02351 return ret; 02352 } 02353 02354 static BOOL CDecodeMsg_FinalizeEnvelopedContent(CDecodeMsg *msg, 02355 CRYPT_DER_BLOB *blob) 02356 { 02357 CRYPT_DATA_BLOB *content; 02358 02359 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 02360 content = &msg->detached_data; 02361 else 02362 content = 02363 &msg->u.enveloped_data.data->encryptedContentInfo.encryptedContent; 02364 02365 return CRYPT_ConstructBlob(&msg->u.enveloped_data.content, content); 02366 } 02367 02368 static BOOL CDecodeMsg_FinalizeSignedContent(CDecodeMsg *msg, 02369 CRYPT_DER_BLOB *blob) 02370 { 02371 BOOL ret; 02372 DWORD i, size; 02373 02374 ret = CSignedMsgData_AllocateHandles(&msg->u.signed_data); 02375 for (i = 0; ret && i < msg->u.signed_data.info->cSignerInfo; i++) 02376 ret = CSignedMsgData_ConstructSignerHandles(&msg->u.signed_data, i, 02377 msg->crypt_prov); 02378 if (ret) 02379 { 02380 CRYPT_DATA_BLOB *content; 02381 02382 /* Now that we have all the content, update the hash handles with 02383 * it. If the message is a detached message, the content is stored 02384 * in msg->detached_data rather than in the signed message's 02385 * content. 02386 */ 02387 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 02388 content = &msg->detached_data; 02389 else 02390 content = &msg->u.signed_data.info->content.Content; 02391 if (content->cbData) 02392 { 02393 /* If the message is not detached, have to decode the message's 02394 * content if the type is szOID_RSA_data. 02395 */ 02396 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && 02397 !strcmp(msg->u.signed_data.info->content.pszObjId, 02398 szOID_RSA_data)) 02399 { 02400 CRYPT_DATA_BLOB *blob; 02401 02402 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, 02403 X509_OCTET_STRING, content->pbData, content->cbData, 02404 CRYPT_DECODE_ALLOC_FLAG, NULL, &blob, &size); 02405 if (ret) 02406 { 02407 ret = CSignedMsgData_Update(&msg->u.signed_data, 02408 blob->pbData, blob->cbData, TRUE, Verify); 02409 LocalFree(blob); 02410 } 02411 } 02412 else 02413 ret = CSignedMsgData_Update(&msg->u.signed_data, 02414 content->pbData, content->cbData, TRUE, Verify); 02415 } 02416 } 02417 return ret; 02418 } 02419 02420 static BOOL CDecodeMsg_FinalizeContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob) 02421 { 02422 BOOL ret = FALSE; 02423 02424 switch (msg->type) 02425 { 02426 case CMSG_HASHED: 02427 ret = CDecodeMsg_FinalizeHashedContent(msg, blob); 02428 break; 02429 case CMSG_ENVELOPED: 02430 ret = CDecodeMsg_FinalizeEnvelopedContent(msg, blob); 02431 break; 02432 case CMSG_SIGNED: 02433 ret = CDecodeMsg_FinalizeSignedContent(msg, blob); 02434 break; 02435 default: 02436 ret = TRUE; 02437 } 02438 return ret; 02439 } 02440 02441 static BOOL CDecodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, 02442 DWORD cbData, BOOL fFinal) 02443 { 02444 CDecodeMsg *msg = hCryptMsg; 02445 BOOL ret = FALSE; 02446 02447 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal); 02448 02449 if (msg->base.state == MsgStateFinalized) 02450 SetLastError(CRYPT_E_MSG_ERROR); 02451 else if (msg->base.streamed) 02452 { 02453 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg, pbData, 02454 cbData, fFinal); 02455 switch (msg->base.state) 02456 { 02457 case MsgStateInit: 02458 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData); 02459 if (fFinal) 02460 { 02461 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 02462 msg->base.state = MsgStateDataFinalized; 02463 else 02464 msg->base.state = MsgStateFinalized; 02465 } 02466 else 02467 msg->base.state = MsgStateUpdated; 02468 break; 02469 case MsgStateUpdated: 02470 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData); 02471 if (fFinal) 02472 { 02473 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 02474 msg->base.state = MsgStateDataFinalized; 02475 else 02476 msg->base.state = MsgStateFinalized; 02477 } 02478 break; 02479 case MsgStateDataFinalized: 02480 ret = CDecodeMsg_CopyData(&msg->detached_data, pbData, cbData); 02481 if (fFinal) 02482 msg->base.state = MsgStateFinalized; 02483 break; 02484 default: 02485 SetLastError(CRYPT_E_MSG_ERROR); 02486 break; 02487 } 02488 } 02489 else 02490 { 02491 if (!fFinal) 02492 SetLastError(CRYPT_E_MSG_ERROR); 02493 else 02494 { 02495 switch (msg->base.state) 02496 { 02497 case MsgStateInit: 02498 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData); 02499 if (msg->base.open_flags & CMSG_DETACHED_FLAG) 02500 msg->base.state = MsgStateDataFinalized; 02501 else 02502 msg->base.state = MsgStateFinalized; 02503 break; 02504 case MsgStateDataFinalized: 02505 ret = CDecodeMsg_CopyData(&msg->detached_data, pbData, cbData); 02506 msg->base.state = MsgStateFinalized; 02507 break; 02508 default: 02509 SetLastError(CRYPT_E_MSG_ERROR); 02510 } 02511 } 02512 } 02513 if (ret && fFinal && 02514 ((msg->base.open_flags & CMSG_DETACHED_FLAG && msg->base.state == 02515 MsgStateDataFinalized) || 02516 (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && msg->base.state == 02517 MsgStateFinalized))) 02518 ret = CDecodeMsg_DecodeContent(msg, &msg->msg_data, msg->type); 02519 if (ret && msg->base.state == MsgStateFinalized) 02520 ret = CDecodeMsg_FinalizeContent(msg, &msg->msg_data); 02521 return ret; 02522 } 02523 02524 static BOOL CDecodeHashMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType, 02525 DWORD dwIndex, void *pvData, DWORD *pcbData) 02526 { 02527 BOOL ret = FALSE; 02528 02529 switch (dwParamType) 02530 { 02531 case CMSG_TYPE_PARAM: 02532 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type)); 02533 break; 02534 case CMSG_HASH_ALGORITHM_PARAM: 02535 { 02536 CRYPT_DATA_BLOB blob; 02537 02538 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType, 02539 &blob); 02540 if (ret) 02541 { 02542 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, blob.cbData); 02543 if (ret && pvData) 02544 CRYPT_FixUpAlgorithmID(pvData); 02545 } 02546 else 02547 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 02548 break; 02549 } 02550 case CMSG_COMPUTED_HASH_PARAM: 02551 ret = CryptGetHashParam(msg->u.hash, HP_HASHVAL, pvData, pcbData, 0); 02552 break; 02553 default: 02554 { 02555 CRYPT_DATA_BLOB blob; 02556 02557 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType, 02558 &blob); 02559 if (ret) 02560 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, blob.cbData); 02561 else 02562 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 02563 } 02564 } 02565 return ret; 02566 } 02567 02568 /* nextData is an in/out parameter - on input it's the memory location in 02569 * which a copy of in's data should be made, and on output it's the memory 02570 * location immediately after out's copy of in's data. 02571 */ 02572 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB *out, 02573 const CRYPT_DATA_BLOB *in, LPBYTE *nextData) 02574 { 02575 out->cbData = in->cbData; 02576 if (in->cbData) 02577 { 02578 out->pbData = *nextData; 02579 memcpy(out->pbData, in->pbData, in->cbData); 02580 *nextData += in->cbData; 02581 } 02582 } 02583 02584 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER *out, 02585 const CRYPT_ALGORITHM_IDENTIFIER *in, LPBYTE *nextData) 02586 { 02587 if (in->pszObjId) 02588 { 02589 out->pszObjId = (LPSTR)*nextData; 02590 strcpy(out->pszObjId, in->pszObjId); 02591 *nextData += strlen(out->pszObjId) + 1; 02592 } 02593 CRYPT_CopyBlob(&out->Parameters, &in->Parameters, nextData); 02594 } 02595 02596 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out, 02597 const CRYPT_ATTRIBUTES *in, LPBYTE *nextData) 02598 { 02599 out->cAttr = in->cAttr; 02600 if (in->cAttr) 02601 { 02602 DWORD i; 02603 02604 *nextData = POINTER_ALIGN_DWORD_PTR(*nextData); 02605 out->rgAttr = (CRYPT_ATTRIBUTE *)*nextData; 02606 *nextData += in->cAttr * sizeof(CRYPT_ATTRIBUTE); 02607 for (i = 0; i < in->cAttr; i++) 02608 { 02609 if (in->rgAttr[i].pszObjId) 02610 { 02611 out->rgAttr[i].pszObjId = (LPSTR)*nextData; 02612 strcpy(out->rgAttr[i].pszObjId, in->rgAttr[i].pszObjId); 02613 *nextData += strlen(in->rgAttr[i].pszObjId) + 1; 02614 } 02615 if (in->rgAttr[i].cValue) 02616 { 02617 DWORD j; 02618 02619 out->rgAttr[i].cValue = in->rgAttr[i].cValue; 02620 *nextData = POINTER_ALIGN_DWORD_PTR(*nextData); 02621 out->rgAttr[i].rgValue = (PCRYPT_DATA_BLOB)*nextData; 02622 *nextData += in->rgAttr[i].cValue * sizeof(CRYPT_DATA_BLOB); 02623 for (j = 0; j < in->rgAttr[i].cValue; j++) 02624 CRYPT_CopyBlob(&out->rgAttr[i].rgValue[j], 02625 &in->rgAttr[i].rgValue[j], nextData); 02626 } 02627 } 02628 } 02629 } 02630 02631 static DWORD CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES *attr) 02632 { 02633 DWORD size = attr->cAttr * sizeof(CRYPT_ATTRIBUTE), i, j; 02634 02635 for (i = 0; i < attr->cAttr; i++) 02636 { 02637 if (attr->rgAttr[i].pszObjId) 02638 size += strlen(attr->rgAttr[i].pszObjId) + 1; 02639 /* align pointer */ 02640 size = ALIGN_DWORD_PTR(size); 02641 size += attr->rgAttr[i].cValue * sizeof(CRYPT_DATA_BLOB); 02642 for (j = 0; j < attr->rgAttr[i].cValue; j++) 02643 size += attr->rgAttr[i].rgValue[j].cbData; 02644 } 02645 /* align pointer again to be conservative */ 02646 size = ALIGN_DWORD_PTR(size); 02647 return size; 02648 } 02649 02650 static DWORD CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB *keyId) 02651 { 02652 static char oid_key_rdn[] = szOID_KEYID_RDN; 02653 DWORD size = 0; 02654 CERT_RDN_ATTR attr; 02655 CERT_RDN rdn = { 1, &attr }; 02656 CERT_NAME_INFO name = { 1, &rdn }; 02657 02658 attr.pszObjId = oid_key_rdn; 02659 attr.dwValueType = CERT_RDN_OCTET_STRING; 02660 attr.Value.cbData = keyId->cbData; 02661 attr.Value.pbData = keyId->pbData; 02662 if (CryptEncodeObject(X509_ASN_ENCODING, X509_NAME, &name, NULL, &size)) 02663 size++; /* Only include size of special zero serial number on success */ 02664 return size; 02665 } 02666 02667 static BOOL CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB *issuer, 02668 CRYPT_INTEGER_BLOB *serialNumber, const CRYPT_DATA_BLOB *keyId, DWORD encodedLen, 02669 LPBYTE *nextData) 02670 { 02671 static char oid_key_rdn[] = szOID_KEYID_RDN; 02672 CERT_RDN_ATTR attr; 02673 CERT_RDN rdn = { 1, &attr }; 02674 CERT_NAME_INFO name = { 1, &rdn }; 02675 BOOL ret; 02676 02677 /* Encode special zero serial number */ 02678 serialNumber->cbData = 1; 02679 serialNumber->pbData = *nextData; 02680 **nextData = 0; 02681 (*nextData)++; 02682 /* Encode issuer */ 02683 issuer->pbData = *nextData; 02684 attr.pszObjId = oid_key_rdn; 02685 attr.dwValueType = CERT_RDN_OCTET_STRING; 02686 attr.Value.cbData = keyId->cbData; 02687 attr.Value.pbData = keyId->pbData; 02688 ret = CryptEncodeObject(X509_ASN_ENCODING, X509_NAME, &name, *nextData, 02689 &encodedLen); 02690 if (ret) 02691 { 02692 *nextData += encodedLen; 02693 issuer->cbData = encodedLen; 02694 } 02695 return ret; 02696 } 02697 02698 static BOOL CRYPT_CopySignerInfo(void *pvData, DWORD *pcbData, 02699 const CMSG_CMS_SIGNER_INFO *in) 02700 { 02701 DWORD size = sizeof(CMSG_SIGNER_INFO), rdnSize = 0; 02702 BOOL ret; 02703 02704 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in); 02705 02706 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 02707 { 02708 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData; 02709 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData; 02710 } 02711 else 02712 { 02713 rdnSize = CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in->SignerId.u.KeyId); 02714 size += rdnSize; 02715 } 02716 if (in->HashAlgorithm.pszObjId) 02717 size += strlen(in->HashAlgorithm.pszObjId) + 1; 02718 size += in->HashAlgorithm.Parameters.cbData; 02719 if (in->HashEncryptionAlgorithm.pszObjId) 02720 size += strlen(in->HashEncryptionAlgorithm.pszObjId) + 1; 02721 size += in->HashEncryptionAlgorithm.Parameters.cbData; 02722 size += in->EncryptedHash.cbData; 02723 /* align pointer */ 02724 size = ALIGN_DWORD_PTR(size); 02725 size += CRYPT_SizeOfAttributes(&in->AuthAttrs); 02726 size += CRYPT_SizeOfAttributes(&in->UnauthAttrs); 02727 if (!pvData) 02728 { 02729 *pcbData = size; 02730 ret = TRUE; 02731 } 02732 else if (*pcbData < size) 02733 { 02734 *pcbData = size; 02735 SetLastError(ERROR_MORE_DATA); 02736 ret = FALSE; 02737 } 02738 else 02739 { 02740 LPBYTE nextData = (BYTE *)pvData + sizeof(CMSG_SIGNER_INFO); 02741 CMSG_SIGNER_INFO *out = pvData; 02742 02743 ret = TRUE; 02744 out->dwVersion = in->dwVersion; 02745 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 02746 { 02747 CRYPT_CopyBlob(&out->Issuer, 02748 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData); 02749 CRYPT_CopyBlob(&out->SerialNumber, 02750 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData); 02751 } 02752 else 02753 ret = CRYPT_CopyKeyIdAsIssuerAndSerial(&out->Issuer, &out->SerialNumber, 02754 &in->SignerId.u.KeyId, rdnSize, &nextData); 02755 if (ret) 02756 { 02757 CRYPT_CopyAlgorithmId(&out->HashAlgorithm, &in->HashAlgorithm, 02758 &nextData); 02759 CRYPT_CopyAlgorithmId(&out->HashEncryptionAlgorithm, 02760 &in->HashEncryptionAlgorithm, &nextData); 02761 CRYPT_CopyBlob(&out->EncryptedHash, &in->EncryptedHash, &nextData); 02762 nextData = POINTER_ALIGN_DWORD_PTR(nextData); 02763 CRYPT_CopyAttributes(&out->AuthAttrs, &in->AuthAttrs, &nextData); 02764 CRYPT_CopyAttributes(&out->UnauthAttrs, &in->UnauthAttrs, &nextData); 02765 } 02766 } 02767 TRACE("returning %d\n", ret); 02768 return ret; 02769 } 02770 02771 static BOOL CRYPT_CopyCMSSignerInfo(void *pvData, DWORD *pcbData, 02772 const CMSG_CMS_SIGNER_INFO *in) 02773 { 02774 DWORD size = sizeof(CMSG_CMS_SIGNER_INFO); 02775 BOOL ret; 02776 02777 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in); 02778 02779 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 02780 { 02781 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData; 02782 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData; 02783 } 02784 else 02785 size += in->SignerId.u.KeyId.cbData; 02786 if (in->HashAlgorithm.pszObjId) 02787 size += strlen(in->HashAlgorithm.pszObjId) + 1; 02788 size += in->HashAlgorithm.Parameters.cbData; 02789 if (in->HashEncryptionAlgorithm.pszObjId) 02790 size += strlen(in->HashEncryptionAlgorithm.pszObjId) + 1; 02791 size += in->HashEncryptionAlgorithm.Parameters.cbData; 02792 size += in->EncryptedHash.cbData; 02793 /* align pointer */ 02794 size = ALIGN_DWORD_PTR(size); 02795 size += CRYPT_SizeOfAttributes(&in->AuthAttrs); 02796 size += CRYPT_SizeOfAttributes(&in->UnauthAttrs); 02797 if (!pvData) 02798 { 02799 *pcbData = size; 02800 ret = TRUE; 02801 } 02802 else if (*pcbData < size) 02803 { 02804 *pcbData = size; 02805 SetLastError(ERROR_MORE_DATA); 02806 ret = FALSE; 02807 } 02808 else 02809 { 02810 LPBYTE nextData = (BYTE *)pvData + sizeof(CMSG_CMS_SIGNER_INFO); 02811 CMSG_CMS_SIGNER_INFO *out = pvData; 02812 02813 out->dwVersion = in->dwVersion; 02814 out->SignerId.dwIdChoice = in->SignerId.dwIdChoice; 02815 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 02816 { 02817 CRYPT_CopyBlob(&out->SignerId.u.IssuerSerialNumber.Issuer, 02818 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData); 02819 CRYPT_CopyBlob(&out->SignerId.u.IssuerSerialNumber.SerialNumber, 02820 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData); 02821 } 02822 else 02823 CRYPT_CopyBlob(&out->SignerId.u.KeyId, &in->SignerId.u.KeyId, &nextData); 02824 CRYPT_CopyAlgorithmId(&out->HashAlgorithm, &in->HashAlgorithm, 02825 &nextData); 02826 CRYPT_CopyAlgorithmId(&out->HashEncryptionAlgorithm, 02827 &in->HashEncryptionAlgorithm, &nextData); 02828 CRYPT_CopyBlob(&out->EncryptedHash, &in->EncryptedHash, &nextData); 02829 nextData = POINTER_ALIGN_DWORD_PTR(nextData); 02830 CRYPT_CopyAttributes(&out->AuthAttrs, &in->AuthAttrs, &nextData); 02831 CRYPT_CopyAttributes(&out->UnauthAttrs, &in->UnauthAttrs, &nextData); 02832 ret = TRUE; 02833 } 02834 TRACE("returning %d\n", ret); 02835 return ret; 02836 } 02837 02838 static BOOL CRYPT_CopySignerCertInfo(void *pvData, DWORD *pcbData, 02839 const CMSG_CMS_SIGNER_INFO *in) 02840 { 02841 DWORD size = sizeof(CERT_INFO), rdnSize = 0; 02842 BOOL ret; 02843 02844 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in); 02845 02846 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 02847 { 02848 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData; 02849 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData; 02850 } 02851 else 02852 { 02853 rdnSize = CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in->SignerId.u.KeyId); 02854 size += rdnSize; 02855 } 02856 if (!pvData) 02857 { 02858 *pcbData = size; 02859 ret = TRUE; 02860 } 02861 else if (*pcbData < size) 02862 { 02863 *pcbData = size; 02864 SetLastError(ERROR_MORE_DATA); 02865 ret = FALSE; 02866 } 02867 else 02868 { 02869 LPBYTE nextData = (BYTE *)pvData + sizeof(CERT_INFO); 02870 CERT_INFO *out = pvData; 02871 02872 memset(out, 0, sizeof(CERT_INFO)); 02873 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 02874 { 02875 CRYPT_CopyBlob(&out->Issuer, 02876 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData); 02877 CRYPT_CopyBlob(&out->SerialNumber, 02878 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData); 02879 ret = TRUE; 02880 } 02881 else 02882 ret = CRYPT_CopyKeyIdAsIssuerAndSerial(&out->Issuer, &out->SerialNumber, 02883 &in->SignerId.u.KeyId, rdnSize, &nextData); 02884 } 02885 TRACE("returning %d\n", ret); 02886 return ret; 02887 } 02888 02889 static BOOL CRYPT_CopyRecipientInfo(void *pvData, DWORD *pcbData, 02890 const CERT_ISSUER_SERIAL_NUMBER *in) 02891 { 02892 DWORD size = sizeof(CERT_INFO); 02893 BOOL ret; 02894 02895 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in); 02896 02897 size += in->SerialNumber.cbData; 02898 size += in->Issuer.cbData; 02899 if (!pvData) 02900 { 02901 *pcbData = size; 02902 ret = TRUE; 02903 } 02904 else if (*pcbData < size) 02905 { 02906 *pcbData = size; 02907 SetLastError(ERROR_MORE_DATA); 02908 ret = FALSE; 02909 } 02910 else 02911 { 02912 LPBYTE nextData = (BYTE *)pvData + sizeof(CERT_INFO); 02913 CERT_INFO *out = pvData; 02914 02915 CRYPT_CopyBlob(&out->SerialNumber, &in->SerialNumber, &nextData); 02916 CRYPT_CopyBlob(&out->Issuer, &in->Issuer, &nextData); 02917 ret = TRUE; 02918 } 02919 TRACE("returning %d\n", ret); 02920 return ret; 02921 } 02922 02923 static BOOL CDecodeEnvelopedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType, 02924 DWORD dwIndex, void *pvData, DWORD *pcbData) 02925 { 02926 BOOL ret = FALSE; 02927 02928 switch (dwParamType) 02929 { 02930 case CMSG_TYPE_PARAM: 02931 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type)); 02932 break; 02933 case CMSG_CONTENT_PARAM: 02934 if (msg->u.enveloped_data.data) 02935 ret = CRYPT_CopyParam(pvData, pcbData, 02936 msg->u.enveloped_data.content.pbData, 02937 msg->u.enveloped_data.content.cbData); 02938 else 02939 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 02940 break; 02941 case CMSG_RECIPIENT_COUNT_PARAM: 02942 if (msg->u.enveloped_data.data) 02943 ret = CRYPT_CopyParam(pvData, pcbData, 02944 &msg->u.enveloped_data.data->cRecipientInfo, sizeof(DWORD)); 02945 else 02946 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 02947 break; 02948 case CMSG_RECIPIENT_INFO_PARAM: 02949 if (msg->u.enveloped_data.data) 02950 { 02951 if (dwIndex < msg->u.enveloped_data.data->cRecipientInfo) 02952 { 02953 PCMSG_KEY_TRANS_RECIPIENT_INFO recipientInfo = 02954 &msg->u.enveloped_data.data->rgRecipientInfo[dwIndex]; 02955 02956 ret = CRYPT_CopyRecipientInfo(pvData, pcbData, 02957 &recipientInfo->RecipientId.u.IssuerSerialNumber); 02958 } 02959 else 02960 SetLastError(CRYPT_E_INVALID_INDEX); 02961 } 02962 else 02963 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 02964 break; 02965 default: 02966 FIXME("unimplemented for %d\n", dwParamType); 02967 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 02968 } 02969 return ret; 02970 } 02971 02972 static BOOL CDecodeSignedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType, 02973 DWORD dwIndex, void *pvData, DWORD *pcbData) 02974 { 02975 BOOL ret = FALSE; 02976 02977 switch (dwParamType) 02978 { 02979 case CMSG_TYPE_PARAM: 02980 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type)); 02981 break; 02982 case CMSG_CONTENT_PARAM: 02983 if (msg->u.signed_data.info) 02984 { 02985 if (!strcmp(msg->u.signed_data.info->content.pszObjId, 02986 szOID_RSA_data)) 02987 { 02988 CRYPT_DATA_BLOB *blob; 02989 DWORD size; 02990 02991 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, 02992 msg->u.signed_data.info->content.Content.pbData, 02993 msg->u.signed_data.info->content.Content.cbData, 02994 CRYPT_DECODE_ALLOC_FLAG, NULL, &blob, &size); 02995 if (ret) 02996 { 02997 ret = CRYPT_CopyParam(pvData, pcbData, blob->pbData, 02998 blob->cbData); 02999 LocalFree(blob); 03000 } 03001 } 03002 else 03003 ret = CRYPT_CopyParam(pvData, pcbData, 03004 msg->u.signed_data.info->content.Content.pbData, 03005 msg->u.signed_data.info->content.Content.cbData); 03006 } 03007 else 03008 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03009 break; 03010 case CMSG_INNER_CONTENT_TYPE_PARAM: 03011 if (msg->u.signed_data.info) 03012 ret = CRYPT_CopyParam(pvData, pcbData, 03013 msg->u.signed_data.info->content.pszObjId, 03014 strlen(msg->u.signed_data.info->content.pszObjId) + 1); 03015 else 03016 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03017 break; 03018 case CMSG_SIGNER_COUNT_PARAM: 03019 if (msg->u.signed_data.info) 03020 ret = CRYPT_CopyParam(pvData, pcbData, 03021 &msg->u.signed_data.info->cSignerInfo, sizeof(DWORD)); 03022 else 03023 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03024 break; 03025 case CMSG_SIGNER_INFO_PARAM: 03026 if (msg->u.signed_data.info) 03027 { 03028 if (dwIndex >= msg->u.signed_data.info->cSignerInfo) 03029 SetLastError(CRYPT_E_INVALID_INDEX); 03030 else 03031 ret = CRYPT_CopySignerInfo(pvData, pcbData, 03032 &msg->u.signed_data.info->rgSignerInfo[dwIndex]); 03033 } 03034 else 03035 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03036 break; 03037 case CMSG_SIGNER_CERT_INFO_PARAM: 03038 if (msg->u.signed_data.info) 03039 { 03040 if (dwIndex >= msg->u.signed_data.info->cSignerInfo) 03041 SetLastError(CRYPT_E_INVALID_INDEX); 03042 else 03043 ret = CRYPT_CopySignerCertInfo(pvData, pcbData, 03044 &msg->u.signed_data.info->rgSignerInfo[dwIndex]); 03045 } 03046 else 03047 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03048 break; 03049 case CMSG_CERT_COUNT_PARAM: 03050 if (msg->u.signed_data.info) 03051 ret = CRYPT_CopyParam(pvData, pcbData, 03052 &msg->u.signed_data.info->cCertEncoded, sizeof(DWORD)); 03053 else 03054 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03055 break; 03056 case CMSG_CERT_PARAM: 03057 if (msg->u.signed_data.info) 03058 { 03059 if (dwIndex >= msg->u.signed_data.info->cCertEncoded) 03060 SetLastError(CRYPT_E_INVALID_INDEX); 03061 else 03062 ret = CRYPT_CopyParam(pvData, pcbData, 03063 msg->u.signed_data.info->rgCertEncoded[dwIndex].pbData, 03064 msg->u.signed_data.info->rgCertEncoded[dwIndex].cbData); 03065 } 03066 else 03067 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03068 break; 03069 case CMSG_CRL_COUNT_PARAM: 03070 if (msg->u.signed_data.info) 03071 ret = CRYPT_CopyParam(pvData, pcbData, 03072 &msg->u.signed_data.info->cCrlEncoded, sizeof(DWORD)); 03073 else 03074 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03075 break; 03076 case CMSG_CRL_PARAM: 03077 if (msg->u.signed_data.info) 03078 { 03079 if (dwIndex >= msg->u.signed_data.info->cCrlEncoded) 03080 SetLastError(CRYPT_E_INVALID_INDEX); 03081 else 03082 ret = CRYPT_CopyParam(pvData, pcbData, 03083 msg->u.signed_data.info->rgCrlEncoded[dwIndex].pbData, 03084 msg->u.signed_data.info->rgCrlEncoded[dwIndex].cbData); 03085 } 03086 else 03087 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03088 break; 03089 case CMSG_COMPUTED_HASH_PARAM: 03090 if (msg->u.signed_data.info) 03091 { 03092 if (dwIndex >= msg->u.signed_data.cSignerHandle) 03093 SetLastError(CRYPT_E_INVALID_INDEX); 03094 else 03095 ret = CryptGetHashParam( 03096 msg->u.signed_data.signerHandles[dwIndex].contentHash, 03097 HP_HASHVAL, pvData, pcbData, 0); 03098 } 03099 else 03100 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03101 break; 03102 case CMSG_ENCODED_SIGNER: 03103 if (msg->u.signed_data.info) 03104 { 03105 if (dwIndex >= msg->u.signed_data.info->cSignerInfo) 03106 SetLastError(CRYPT_E_INVALID_INDEX); 03107 else 03108 ret = CryptEncodeObjectEx( 03109 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CMS_SIGNER_INFO, 03110 &msg->u.signed_data.info->rgSignerInfo[dwIndex], 0, NULL, 03111 pvData, pcbData); 03112 } 03113 else 03114 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03115 break; 03116 case CMSG_ATTR_CERT_COUNT_PARAM: 03117 if (msg->u.signed_data.info) 03118 { 03119 DWORD attrCertCount = 0; 03120 03121 ret = CRYPT_CopyParam(pvData, pcbData, 03122 &attrCertCount, sizeof(DWORD)); 03123 } 03124 else 03125 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03126 break; 03127 case CMSG_ATTR_CERT_PARAM: 03128 if (msg->u.signed_data.info) 03129 SetLastError(CRYPT_E_INVALID_INDEX); 03130 else 03131 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03132 break; 03133 case CMSG_CMS_SIGNER_INFO_PARAM: 03134 if (msg->u.signed_data.info) 03135 { 03136 if (dwIndex >= msg->u.signed_data.info->cSignerInfo) 03137 SetLastError(CRYPT_E_INVALID_INDEX); 03138 else 03139 ret = CRYPT_CopyCMSSignerInfo(pvData, pcbData, 03140 &msg->u.signed_data.info->rgSignerInfo[dwIndex]); 03141 } 03142 else 03143 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03144 break; 03145 default: 03146 FIXME("unimplemented for %d\n", dwParamType); 03147 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03148 } 03149 return ret; 03150 } 03151 03152 static BOOL CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 03153 DWORD dwIndex, void *pvData, DWORD *pcbData) 03154 { 03155 CDecodeMsg *msg = hCryptMsg; 03156 BOOL ret = FALSE; 03157 03158 switch (msg->type) 03159 { 03160 case CMSG_HASHED: 03161 ret = CDecodeHashMsg_GetParam(msg, dwParamType, dwIndex, pvData, 03162 pcbData); 03163 break; 03164 case CMSG_ENVELOPED: 03165 ret = CDecodeEnvelopedMsg_GetParam(msg, dwParamType, dwIndex, pvData, 03166 pcbData); 03167 break; 03168 case CMSG_SIGNED: 03169 ret = CDecodeSignedMsg_GetParam(msg, dwParamType, dwIndex, pvData, 03170 pcbData); 03171 break; 03172 default: 03173 switch (dwParamType) 03174 { 03175 case CMSG_TYPE_PARAM: 03176 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, 03177 sizeof(msg->type)); 03178 break; 03179 default: 03180 { 03181 CRYPT_DATA_BLOB blob; 03182 03183 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType, 03184 &blob); 03185 if (ret) 03186 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, 03187 blob.cbData); 03188 else 03189 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03190 } 03191 } 03192 } 03193 return ret; 03194 } 03195 03196 static BOOL CDecodeHashMsg_VerifyHash(CDecodeMsg *msg) 03197 { 03198 BOOL ret; 03199 CRYPT_DATA_BLOB hashBlob; 03200 03201 ret = ContextPropertyList_FindProperty(msg->properties, 03202 CMSG_HASH_DATA_PARAM, &hashBlob); 03203 if (ret) 03204 { 03205 DWORD computedHashSize = 0; 03206 03207 ret = CDecodeHashMsg_GetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, 03208 &computedHashSize); 03209 if (hashBlob.cbData == computedHashSize) 03210 { 03211 LPBYTE computedHash = CryptMemAlloc(computedHashSize); 03212 03213 if (computedHash) 03214 { 03215 ret = CDecodeHashMsg_GetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, 03216 computedHash, &computedHashSize); 03217 if (ret) 03218 { 03219 if (memcmp(hashBlob.pbData, computedHash, hashBlob.cbData)) 03220 { 03221 SetLastError(CRYPT_E_HASH_VALUE); 03222 ret = FALSE; 03223 } 03224 } 03225 CryptMemFree(computedHash); 03226 } 03227 else 03228 { 03229 SetLastError(ERROR_OUTOFMEMORY); 03230 ret = FALSE; 03231 } 03232 } 03233 else 03234 { 03235 SetLastError(CRYPT_E_HASH_VALUE); 03236 ret = FALSE; 03237 } 03238 } 03239 return ret; 03240 } 03241 03242 static BOOL CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg *msg, 03243 HCRYPTPROV prov, DWORD signerIndex, PCERT_PUBLIC_KEY_INFO keyInfo) 03244 { 03245 HCRYPTKEY key; 03246 BOOL ret; 03247 03248 if (!prov) 03249 prov = msg->crypt_prov; 03250 ret = CryptImportPublicKeyInfo(prov, X509_ASN_ENCODING, keyInfo, &key); 03251 if (ret) 03252 { 03253 HCRYPTHASH hash; 03254 CRYPT_HASH_BLOB reversedHash; 03255 03256 if (msg->u.signed_data.info->rgSignerInfo[signerIndex].AuthAttrs.cAttr) 03257 hash = msg->u.signed_data.signerHandles[signerIndex].authAttrHash; 03258 else 03259 hash = msg->u.signed_data.signerHandles[signerIndex].contentHash; 03260 ret = CRYPT_ConstructBlob(&reversedHash, 03261 &msg->u.signed_data.info->rgSignerInfo[signerIndex].EncryptedHash); 03262 if (ret) 03263 { 03264 CRYPT_ReverseBytes(&reversedHash); 03265 ret = CryptVerifySignatureW(hash, reversedHash.pbData, 03266 reversedHash.cbData, key, NULL, 0); 03267 CryptMemFree(reversedHash.pbData); 03268 } 03269 CryptDestroyKey(key); 03270 } 03271 return ret; 03272 } 03273 03274 static BOOL CDecodeSignedMsg_VerifySignature(CDecodeMsg *msg, PCERT_INFO info) 03275 { 03276 BOOL ret = FALSE; 03277 DWORD i; 03278 03279 if (!msg->u.signed_data.signerHandles) 03280 { 03281 SetLastError(NTE_BAD_SIGNATURE); 03282 return FALSE; 03283 } 03284 for (i = 0; !ret && i < msg->u.signed_data.info->cSignerInfo; i++) 03285 { 03286 PCMSG_CMS_SIGNER_INFO signerInfo = 03287 &msg->u.signed_data.info->rgSignerInfo[i]; 03288 03289 if (signerInfo->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 03290 { 03291 ret = CertCompareCertificateName(X509_ASN_ENCODING, 03292 &signerInfo->SignerId.u.IssuerSerialNumber.Issuer, 03293 &info->Issuer); 03294 if (ret) 03295 { 03296 ret = CertCompareIntegerBlob( 03297 &signerInfo->SignerId.u.IssuerSerialNumber.SerialNumber, 03298 &info->SerialNumber); 03299 if (ret) 03300 break; 03301 } 03302 } 03303 else 03304 { 03305 FIXME("signer %d: unimplemented for key id\n", i); 03306 } 03307 } 03308 if (ret) 03309 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, 0, i, 03310 &info->SubjectPublicKeyInfo); 03311 else 03312 SetLastError(CRYPT_E_SIGNER_NOT_FOUND); 03313 03314 return ret; 03315 } 03316 03317 static BOOL CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg *msg, 03318 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para) 03319 { 03320 BOOL ret = FALSE; 03321 03322 if (para->cbSize != sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA)) 03323 SetLastError(ERROR_INVALID_PARAMETER); 03324 else if (para->dwSignerIndex >= msg->u.signed_data.info->cSignerInfo) 03325 SetLastError(CRYPT_E_SIGNER_NOT_FOUND); 03326 else if (!msg->u.signed_data.signerHandles) 03327 SetLastError(NTE_BAD_SIGNATURE); 03328 else 03329 { 03330 switch (para->dwSignerType) 03331 { 03332 case CMSG_VERIFY_SIGNER_PUBKEY: 03333 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, 03334 para->hCryptProv, para->dwSignerIndex, para->pvSigner); 03335 break; 03336 case CMSG_VERIFY_SIGNER_CERT: 03337 { 03338 PCCERT_CONTEXT cert = para->pvSigner; 03339 03340 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, para->hCryptProv, 03341 para->dwSignerIndex, &cert->pCertInfo->SubjectPublicKeyInfo); 03342 break; 03343 } 03344 default: 03345 FIXME("unimplemented for signer type %d\n", para->dwSignerType); 03346 SetLastError(CRYPT_E_SIGNER_NOT_FOUND); 03347 } 03348 } 03349 return ret; 03350 } 03351 03352 static BOOL WINAPI CRYPT_ImportKeyTrans( 03353 PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm, 03354 PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara, DWORD dwFlags, 03355 void *pvReserved, HCRYPTKEY *phContentEncryptKey) 03356 { 03357 BOOL ret; 03358 HCRYPTKEY key; 03359 03360 ret = CryptGetUserKey(pKeyTransDecryptPara->hCryptProv, 03361 pKeyTransDecryptPara->dwKeySpec ? pKeyTransDecryptPara->dwKeySpec : 03362 AT_KEYEXCHANGE, &key); 03363 if (ret) 03364 { 03365 CMSG_KEY_TRANS_RECIPIENT_INFO *info = 03366 &pKeyTransDecryptPara->pKeyTrans[pKeyTransDecryptPara->dwRecipientIndex]; 03367 CRYPT_DATA_BLOB *encryptedKey = &info->EncryptedKey; 03368 DWORD size = encryptedKey->cbData + sizeof(BLOBHEADER) + sizeof(ALG_ID); 03369 BYTE *keyBlob = CryptMemAlloc(size); 03370 03371 if (keyBlob) 03372 { 03373 DWORD i, k = size - 1; 03374 BLOBHEADER *blobHeader = (BLOBHEADER *)keyBlob; 03375 ALG_ID *algID = (ALG_ID *)(keyBlob + sizeof(BLOBHEADER)); 03376 03377 blobHeader->bType = SIMPLEBLOB; 03378 blobHeader->bVersion = CUR_BLOB_VERSION; 03379 blobHeader->reserved = 0; 03380 blobHeader->aiKeyAlg = CertOIDToAlgId( 03381 pContentEncryptionAlgorithm->pszObjId); 03382 *algID = CertOIDToAlgId(info->KeyEncryptionAlgorithm.pszObjId); 03383 for (i = 0; i < encryptedKey->cbData; ++i, --k) 03384 keyBlob[k] = encryptedKey->pbData[i]; 03385 03386 ret = CryptImportKey(pKeyTransDecryptPara->hCryptProv, keyBlob, 03387 size, key, 0, phContentEncryptKey); 03388 CryptMemFree(keyBlob); 03389 } 03390 else 03391 ret = FALSE; 03392 CryptDestroyKey(key); 03393 } 03394 return ret; 03395 } 03396 03397 static BOOL CRYPT_ImportEncryptedKey(PCRYPT_ALGORITHM_IDENTIFIER contEncrAlg, 03398 PCMSG_CTRL_DECRYPT_PARA para, PCMSG_KEY_TRANS_RECIPIENT_INFO info, 03399 HCRYPTKEY *key) 03400 { 03401 static HCRYPTOIDFUNCSET set = NULL; 03402 PFN_CMSG_IMPORT_KEY_TRANS importKeyFunc = NULL; 03403 HCRYPTOIDFUNCADDR hFunc = NULL; 03404 CMSG_CTRL_KEY_TRANS_DECRYPT_PARA decryptPara; 03405 BOOL ret; 03406 03407 memset(&decryptPara, 0, sizeof(decryptPara)); 03408 decryptPara.cbSize = sizeof(decryptPara); 03409 decryptPara.hCryptProv = para->hCryptProv; 03410 decryptPara.dwKeySpec = para->dwKeySpec; 03411 decryptPara.pKeyTrans = info; 03412 decryptPara.dwRecipientIndex = para->dwRecipientIndex; 03413 03414 if (!set) 03415 set = CryptInitOIDFunctionSet(CMSG_OID_IMPORT_KEY_TRANS_FUNC, 0); 03416 CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, contEncrAlg->pszObjId, 0, 03417 (void **)&importKeyFunc, &hFunc); 03418 if (!importKeyFunc) 03419 importKeyFunc = CRYPT_ImportKeyTrans; 03420 ret = importKeyFunc(contEncrAlg, &decryptPara, 0, NULL, key); 03421 if (hFunc) 03422 CryptFreeOIDFunctionAddress(hFunc, 0); 03423 return ret; 03424 } 03425 03426 static BOOL CDecodeEnvelopedMsg_CrtlDecrypt(CDecodeMsg *msg, 03427 PCMSG_CTRL_DECRYPT_PARA para) 03428 { 03429 BOOL ret = FALSE; 03430 CEnvelopedDecodeMsg *enveloped_data = &msg->u.enveloped_data; 03431 CRYPT_ENVELOPED_DATA *data = enveloped_data->data; 03432 03433 if (para->cbSize != sizeof(CMSG_CTRL_DECRYPT_PARA)) 03434 SetLastError(E_INVALIDARG); 03435 else if (!data) 03436 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03437 else if (para->dwRecipientIndex >= data->cRecipientInfo) 03438 SetLastError(CRYPT_E_INVALID_INDEX); 03439 else if (enveloped_data->decrypted) 03440 SetLastError(CRYPT_E_ALREADY_DECRYPTED); 03441 else if (!para->hCryptProv) 03442 SetLastError(ERROR_INVALID_PARAMETER); 03443 else if (enveloped_data->content.cbData) 03444 { 03445 HCRYPTKEY key; 03446 03447 ret = CRYPT_ImportEncryptedKey( 03448 &data->encryptedContentInfo.contentEncryptionAlgorithm, para, 03449 data->rgRecipientInfo, &key); 03450 if (ret) 03451 { 03452 ret = CryptDecrypt(key, 0, TRUE, 0, enveloped_data->content.pbData, 03453 &enveloped_data->content.cbData); 03454 CryptDestroyKey(key); 03455 } 03456 } 03457 else 03458 ret = TRUE; 03459 if (ret) 03460 enveloped_data->decrypted = TRUE; 03461 return ret; 03462 } 03463 03464 static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags, 03465 DWORD dwCtrlType, const void *pvCtrlPara) 03466 { 03467 CDecodeMsg *msg = hCryptMsg; 03468 BOOL ret = FALSE; 03469 03470 switch (dwCtrlType) 03471 { 03472 case CMSG_CTRL_VERIFY_SIGNATURE: 03473 switch (msg->type) 03474 { 03475 case CMSG_SIGNED: 03476 ret = CDecodeSignedMsg_VerifySignature(msg, (PCERT_INFO)pvCtrlPara); 03477 break; 03478 default: 03479 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03480 } 03481 break; 03482 case CMSG_CTRL_DECRYPT: 03483 switch (msg->type) 03484 { 03485 case CMSG_ENVELOPED: 03486 ret = CDecodeEnvelopedMsg_CrtlDecrypt(msg, 03487 (PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara); 03488 if (ret && (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)) 03489 msg->u.enveloped_data.crypt_prov = 03490 ((PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara)->hCryptProv; 03491 break; 03492 default: 03493 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03494 } 03495 break; 03496 case CMSG_CTRL_VERIFY_HASH: 03497 switch (msg->type) 03498 { 03499 case CMSG_HASHED: 03500 ret = CDecodeHashMsg_VerifyHash(msg); 03501 break; 03502 default: 03503 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03504 } 03505 break; 03506 case CMSG_CTRL_VERIFY_SIGNATURE_EX: 03507 switch (msg->type) 03508 { 03509 case CMSG_SIGNED: 03510 ret = CDecodeSignedMsg_VerifySignatureEx(msg, 03511 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA)pvCtrlPara); 03512 break; 03513 default: 03514 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 03515 } 03516 break; 03517 default: 03518 SetLastError(CRYPT_E_CONTROL_TYPE); 03519 } 03520 return ret; 03521 } 03522 03523 HCRYPTMSG WINAPI CryptMsgOpenToDecode(DWORD dwMsgEncodingType, DWORD dwFlags, 03524 DWORD dwMsgType, HCRYPTPROV_LEGACY hCryptProv, PCERT_INFO pRecipientInfo, 03525 PCMSG_STREAM_INFO pStreamInfo) 03526 { 03527 CDecodeMsg *msg; 03528 03529 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType, 03530 dwFlags, dwMsgType, hCryptProv, pRecipientInfo, pStreamInfo); 03531 03532 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING) 03533 { 03534 SetLastError(E_INVALIDARG); 03535 return NULL; 03536 } 03537 msg = CryptMemAlloc(sizeof(CDecodeMsg)); 03538 if (msg) 03539 { 03540 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, 03541 CDecodeMsg_Close, CDecodeMsg_GetParam, CDecodeMsg_Update, 03542 CDecodeMsg_Control); 03543 msg->type = dwMsgType; 03544 if (hCryptProv) 03545 msg->crypt_prov = hCryptProv; 03546 else 03547 { 03548 msg->crypt_prov = CRYPT_GetDefaultProvider(); 03549 msg->base.open_flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; 03550 } 03551 memset(&msg->u, 0, sizeof(msg->u)); 03552 msg->msg_data.cbData = 0; 03553 msg->msg_data.pbData = NULL; 03554 msg->detached_data.cbData = 0; 03555 msg->detached_data.pbData = NULL; 03556 msg->properties = ContextPropertyList_Create(); 03557 } 03558 return msg; 03559 } 03560 03561 HCRYPTMSG WINAPI CryptMsgDuplicate(HCRYPTMSG hCryptMsg) 03562 { 03563 TRACE("(%p)\n", hCryptMsg); 03564 03565 if (hCryptMsg) 03566 { 03567 CryptMsgBase *msg = hCryptMsg; 03568 03569 InterlockedIncrement(&msg->ref); 03570 } 03571 return hCryptMsg; 03572 } 03573 03574 BOOL WINAPI CryptMsgClose(HCRYPTMSG hCryptMsg) 03575 { 03576 TRACE("(%p)\n", hCryptMsg); 03577 03578 if (hCryptMsg) 03579 { 03580 CryptMsgBase *msg = hCryptMsg; 03581 03582 if (InterlockedDecrement(&msg->ref) == 0) 03583 { 03584 TRACE("freeing %p\n", msg); 03585 if (msg->close) 03586 msg->close(msg); 03587 CryptMemFree(msg); 03588 } 03589 } 03590 return TRUE; 03591 } 03592 03593 BOOL WINAPI CryptMsgUpdate(HCRYPTMSG hCryptMsg, const BYTE *pbData, 03594 DWORD cbData, BOOL fFinal) 03595 { 03596 CryptMsgBase *msg = hCryptMsg; 03597 03598 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal); 03599 03600 return msg->update(hCryptMsg, pbData, cbData, fFinal); 03601 } 03602 03603 BOOL WINAPI CryptMsgGetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, 03604 DWORD dwIndex, void *pvData, DWORD *pcbData) 03605 { 03606 CryptMsgBase *msg = hCryptMsg; 03607 03608 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex, 03609 pvData, pcbData); 03610 return msg->get_param(hCryptMsg, dwParamType, dwIndex, pvData, pcbData); 03611 } 03612 03613 BOOL WINAPI CryptMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags, 03614 DWORD dwCtrlType, const void *pvCtrlPara) 03615 { 03616 CryptMsgBase *msg = hCryptMsg; 03617 03618 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg, dwFlags, dwCtrlType, 03619 pvCtrlPara); 03620 return msg->control(hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara); 03621 } 03622 03623 static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg, 03624 DWORD dwSignerIndex) 03625 { 03626 CERT_INFO *certInfo = NULL; 03627 DWORD size; 03628 03629 if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL, 03630 &size)) 03631 { 03632 certInfo = CryptMemAlloc(size); 03633 if (certInfo) 03634 { 03635 if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, 03636 dwSignerIndex, certInfo, &size)) 03637 { 03638 CryptMemFree(certInfo); 03639 certInfo = NULL; 03640 } 03641 } 03642 } 03643 return certInfo; 03644 } 03645 03646 BOOL WINAPI CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg, DWORD cSignerStore, 03647 HCERTSTORE *rghSignerStore, DWORD dwFlags, PCCERT_CONTEXT *ppSigner, 03648 DWORD *pdwSignerIndex) 03649 { 03650 HCERTSTORE store; 03651 DWORD i, signerIndex = 0; 03652 PCCERT_CONTEXT signerCert = NULL; 03653 BOOL ret = FALSE; 03654 03655 TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg, cSignerStore, 03656 rghSignerStore, dwFlags, ppSigner, pdwSignerIndex); 03657 03658 /* Clear output parameters */ 03659 if (ppSigner) 03660 *ppSigner = NULL; 03661 if (pdwSignerIndex && !(dwFlags & CMSG_USE_SIGNER_INDEX_FLAG)) 03662 *pdwSignerIndex = 0; 03663 03664 /* Create store to search for signer certificates */ 03665 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 03666 CERT_STORE_CREATE_NEW_FLAG, NULL); 03667 if (!(dwFlags & CMSG_TRUSTED_SIGNER_FLAG)) 03668 { 03669 HCERTSTORE msgStore = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, 03670 hCryptMsg); 03671 03672 CertAddStoreToCollection(store, msgStore, 0, 0); 03673 CertCloseStore(msgStore, 0); 03674 } 03675 for (i = 0; i < cSignerStore; i++) 03676 CertAddStoreToCollection(store, rghSignerStore[i], 0, 0); 03677 03678 /* Find signer cert */ 03679 if (dwFlags & CMSG_USE_SIGNER_INDEX_FLAG) 03680 { 03681 CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg, 03682 *pdwSignerIndex); 03683 03684 if (signer) 03685 { 03686 signerIndex = *pdwSignerIndex; 03687 signerCert = CertFindCertificateInStore(store, X509_ASN_ENCODING, 03688 0, CERT_FIND_SUBJECT_CERT, signer, NULL); 03689 CryptMemFree(signer); 03690 } 03691 } 03692 else 03693 { 03694 DWORD count, size = sizeof(count); 03695 03696 if (CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_COUNT_PARAM, 0, &count, 03697 &size)) 03698 { 03699 for (i = 0; !signerCert && i < count; i++) 03700 { 03701 CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg, 03702 i); 03703 03704 if (signer) 03705 { 03706 signerCert = CertFindCertificateInStore(store, 03707 X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, signer, 03708 NULL); 03709 if (signerCert) 03710 signerIndex = i; 03711 CryptMemFree(signer); 03712 } 03713 } 03714 } 03715 if (!signerCert) 03716 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER); 03717 } 03718 if (signerCert) 03719 { 03720 if (!(dwFlags & CMSG_SIGNER_ONLY_FLAG)) 03721 ret = CryptMsgControl(hCryptMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE, 03722 signerCert->pCertInfo); 03723 else 03724 ret = TRUE; 03725 if (ret) 03726 { 03727 if (ppSigner) 03728 *ppSigner = CertDuplicateCertificateContext(signerCert); 03729 if (pdwSignerIndex) 03730 *pdwSignerIndex = signerIndex; 03731 } 03732 CertFreeCertificateContext(signerCert); 03733 } 03734 03735 CertCloseStore(store, 0); 03736 return ret; 03737 } 03738 03739 BOOL WINAPI CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv, 03740 DWORD dwEncodingType, PBYTE pbSignerInfo, DWORD cbSignerInfo, 03741 PBYTE pbSignerInfoCountersignature, DWORD cbSignerInfoCountersignature, 03742 DWORD dwSignerType, void *pvSigner, DWORD dwFlags, void *pvReserved) 03743 { 03744 FIXME("(%08lx, %08x, %p, %d, %p, %d, %d, %p, %08x, %p): stub\n", hCryptProv, 03745 dwEncodingType, pbSignerInfo, cbSignerInfo, pbSignerInfoCountersignature, 03746 cbSignerInfoCountersignature, dwSignerType, pvSigner, dwFlags, pvReserved); 03747 return FALSE; 03748 } 03749 03750 BOOL WINAPI CryptMsgEncodeAndSignCTL(DWORD dwMsgEncodingType, 03751 PCTL_INFO pCtlInfo, PCMSG_SIGNED_ENCODE_INFO pSignInfo, DWORD dwFlags, 03752 BYTE *pbEncoded, DWORD *pcbEncoded) 03753 { 03754 BOOL ret; 03755 BYTE *pbCtlContent; 03756 DWORD cbCtlContent; 03757 03758 TRACE("(%08x, %p, %p, %08x, %p, %p)\n", dwMsgEncodingType, pCtlInfo, 03759 pSignInfo, dwFlags, pbEncoded, pcbEncoded); 03760 03761 if (dwFlags) 03762 { 03763 FIXME("unimplemented for flags %08x\n", dwFlags); 03764 return FALSE; 03765 } 03766 if ((ret = CryptEncodeObjectEx(dwMsgEncodingType, PKCS_CTL, pCtlInfo, 03767 CRYPT_ENCODE_ALLOC_FLAG, NULL, &pbCtlContent, &cbCtlContent))) 03768 { 03769 ret = CryptMsgSignCTL(dwMsgEncodingType, pbCtlContent, cbCtlContent, 03770 pSignInfo, dwFlags, pbEncoded, pcbEncoded); 03771 LocalFree(pbCtlContent); 03772 } 03773 return ret; 03774 } 03775 03776 BOOL WINAPI CryptMsgSignCTL(DWORD dwMsgEncodingType, BYTE *pbCtlContent, 03777 DWORD cbCtlContent, PCMSG_SIGNED_ENCODE_INFO pSignInfo, DWORD dwFlags, 03778 BYTE *pbEncoded, DWORD *pcbEncoded) 03779 { 03780 static char oid_ctl[] = szOID_CTL; 03781 BOOL ret; 03782 HCRYPTMSG msg; 03783 03784 TRACE("(%08x, %p, %d, %p, %08x, %p, %p)\n", dwMsgEncodingType, 03785 pbCtlContent, cbCtlContent, pSignInfo, dwFlags, pbEncoded, pcbEncoded); 03786 03787 if (dwFlags) 03788 { 03789 FIXME("unimplemented for flags %08x\n", dwFlags); 03790 return FALSE; 03791 } 03792 msg = CryptMsgOpenToEncode(dwMsgEncodingType, 0, CMSG_SIGNED, pSignInfo, 03793 oid_ctl, NULL); 03794 if (msg) 03795 { 03796 ret = CryptMsgUpdate(msg, pbCtlContent, cbCtlContent, TRUE); 03797 if (ret) 03798 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbEncoded, 03799 pcbEncoded); 03800 CryptMsgClose(msg); 03801 } 03802 else 03803 ret = FALSE; 03804 return ret; 03805 } Generated on Sat May 26 2012 04:21:53 for ReactOS by
1.7.6.1
|