winmm/tests: Add tests for visibility of video window.
[wine.git] / dlls / crypt32 / msg.c
blob63884d0c27506704b4d7a75365e6bf08322ee607
1 /*
2 * Copyright 2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #define NONAMELESSUNION
21 #include "windef.h"
22 #include "winbase.h"
23 #include "wincrypt.h"
24 #include "snmp.h"
26 #include "wine/debug.h"
27 #include "wine/exception.h"
28 #include "crypt32_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
32 /* Called when a message's ref count reaches zero. Free any message-specific
33 * data here.
35 typedef void (*CryptMsgCloseFunc)(HCRYPTMSG msg);
37 typedef BOOL (*CryptMsgGetParamFunc)(HCRYPTMSG hCryptMsg, DWORD dwParamType,
38 DWORD dwIndex, void *pvData, DWORD *pcbData);
40 typedef BOOL (*CryptMsgUpdateFunc)(HCRYPTMSG hCryptMsg, const BYTE *pbData,
41 DWORD cbData, BOOL fFinal);
43 typedef BOOL (*CryptMsgControlFunc)(HCRYPTMSG hCryptMsg, DWORD dwFlags,
44 DWORD dwCtrlType, const void *pvCtrlPara);
46 static BOOL CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags,
47 DWORD dwCtrlType, const void *pvCtrlPara)
49 TRACE("(%p, %08lx, %ld, %p)\n", hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara);
50 SetLastError(E_INVALIDARG);
51 return FALSE;
54 typedef enum _CryptMsgState {
55 MsgStateInit,
56 MsgStateUpdated,
57 MsgStateDataFinalized,
58 MsgStateFinalized
59 } CryptMsgState;
61 typedef struct _CryptMsgBase
63 LONG ref;
64 DWORD open_flags;
65 BOOL streamed;
66 CMSG_STREAM_INFO stream_info;
67 CryptMsgState state;
68 CryptMsgCloseFunc close;
69 CryptMsgUpdateFunc update;
70 CryptMsgGetParamFunc get_param;
71 CryptMsgControlFunc control;
72 } CryptMsgBase;
74 static inline void CryptMsgBase_Init(CryptMsgBase *msg, DWORD dwFlags,
75 PCMSG_STREAM_INFO pStreamInfo, CryptMsgCloseFunc close,
76 CryptMsgGetParamFunc get_param, CryptMsgUpdateFunc update,
77 CryptMsgControlFunc control)
79 msg->ref = 1;
80 msg->open_flags = dwFlags;
81 if (pStreamInfo)
83 msg->streamed = TRUE;
84 msg->stream_info = *pStreamInfo;
86 else
88 msg->streamed = FALSE;
89 memset(&msg->stream_info, 0, sizeof(msg->stream_info));
91 msg->close = close;
92 msg->get_param = get_param;
93 msg->update = update;
94 msg->control = control;
95 msg->state = MsgStateInit;
98 typedef struct _CDataEncodeMsg
100 CryptMsgBase base;
101 DWORD bare_content_len;
102 LPBYTE bare_content;
103 } CDataEncodeMsg;
105 static const BYTE empty_data_content[] = { 0x04,0x00 };
107 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg)
109 CDataEncodeMsg *msg = hCryptMsg;
111 if (msg->bare_content != empty_data_content)
112 LocalFree(msg->bare_content);
115 static BOOL WINAPI CRYPT_EncodeContentLength(DWORD dwCertEncodingType,
116 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
117 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
119 DWORD dataLen = *(DWORD *)pvStructInfo;
120 DWORD lenBytes;
121 BOOL ret = TRUE;
123 /* Trick: report bytes needed based on total message length, even though
124 * the message isn't available yet. The caller will use the length
125 * reported here to encode its length.
127 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
128 if (!pbEncoded)
129 *pcbEncoded = 1 + lenBytes + dataLen;
130 else
132 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
133 pcbEncoded, 1 + lenBytes)))
135 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
136 pbEncoded = *(BYTE **)pbEncoded;
137 *pbEncoded++ = ASN_OCTETSTRING;
138 CRYPT_EncodeLen(dataLen, pbEncoded,
139 &lenBytes);
142 return ret;
145 static BOOL CRYPT_EncodeDataContentInfoHeader(const CDataEncodeMsg *msg,
146 CRYPT_DATA_BLOB *header)
148 BOOL ret;
150 if (msg->base.streamed && msg->base.stream_info.cbContent == 0xffffffff)
152 static const BYTE headerValue[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
153 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
155 header->pbData = LocalAlloc(0, sizeof(headerValue));
156 if (header->pbData)
158 header->cbData = sizeof(headerValue);
159 memcpy(header->pbData, headerValue, sizeof(headerValue));
160 ret = TRUE;
162 else
163 ret = FALSE;
165 else
167 struct AsnConstructedItem constructed = { 0,
168 &msg->base.stream_info.cbContent, CRYPT_EncodeContentLength };
169 struct AsnEncodeSequenceItem items[2] = {
170 { szOID_RSA_data, CRYPT_AsnEncodeOid, 0 },
171 { &constructed, CRYPT_AsnEncodeConstructed, 0 },
174 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
175 ARRAY_SIZE(items), CRYPT_ENCODE_ALLOC_FLAG, NULL,
176 (LPBYTE)&header->pbData, &header->cbData);
177 if (ret)
179 /* Trick: subtract the content length from the reported length,
180 * as the actual content hasn't come yet.
182 header->cbData -= msg->base.stream_info.cbContent;
185 return ret;
188 static BOOL CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
189 DWORD cbData, BOOL fFinal)
191 CDataEncodeMsg *msg = hCryptMsg;
192 BOOL ret = FALSE;
194 if (msg->base.state == MsgStateFinalized)
195 SetLastError(CRYPT_E_MSG_ERROR);
196 else if (msg->base.streamed)
198 __TRY
200 if (msg->base.state != MsgStateUpdated)
202 CRYPT_DATA_BLOB header;
204 ret = CRYPT_EncodeDataContentInfoHeader(msg, &header);
205 if (ret)
207 ret = msg->base.stream_info.pfnStreamOutput(
208 msg->base.stream_info.pvArg, header.pbData, header.cbData,
209 FALSE);
210 LocalFree(header.pbData);
213 /* Curiously, every indefinite-length streamed update appears to
214 * get its own tag and length, regardless of fFinal.
216 if (msg->base.stream_info.cbContent == 0xffffffff)
218 BYTE *header;
219 DWORD headerLen;
221 ret = CRYPT_EncodeContentLength(X509_ASN_ENCODING, NULL,
222 &cbData, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&header,
223 &headerLen);
224 if (ret)
226 ret = msg->base.stream_info.pfnStreamOutput(
227 msg->base.stream_info.pvArg, header, headerLen,
228 FALSE);
229 LocalFree(header);
232 if (!fFinal)
234 ret = msg->base.stream_info.pfnStreamOutput(
235 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData,
236 FALSE);
237 msg->base.state = MsgStateUpdated;
239 else
241 msg->base.state = MsgStateFinalized;
242 if (msg->base.stream_info.cbContent == 0xffffffff)
244 BYTE indefinite_trailer[6] = { 0 };
246 ret = msg->base.stream_info.pfnStreamOutput(
247 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData,
248 FALSE);
249 if (ret)
250 ret = msg->base.stream_info.pfnStreamOutput(
251 msg->base.stream_info.pvArg, indefinite_trailer,
252 sizeof(indefinite_trailer), TRUE);
254 else
255 ret = msg->base.stream_info.pfnStreamOutput(
256 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData, TRUE);
259 __EXCEPT_PAGE_FAULT
261 SetLastError(STATUS_ACCESS_VIOLATION);
262 ret = FALSE;
264 __ENDTRY;
266 else
268 if (!fFinal)
270 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
271 SetLastError(E_INVALIDARG);
272 else
273 SetLastError(CRYPT_E_MSG_ERROR);
275 else
277 CRYPT_DATA_BLOB blob = { cbData, (LPBYTE)pbData };
279 msg->base.state = MsgStateFinalized;
280 /* non-streamed data messages don't allow non-final updates,
281 * don't bother checking whether data already exist, they can't.
283 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
284 &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL, &msg->bare_content,
285 &msg->bare_content_len);
288 return ret;
291 static BOOL CRYPT_CopyParam(void *pvData, DWORD *pcbData, const void *src,
292 DWORD len)
294 BOOL ret = TRUE;
296 if (!pvData)
297 *pcbData = len;
298 else if (*pcbData < len)
300 *pcbData = len;
301 SetLastError(ERROR_MORE_DATA);
302 ret = FALSE;
304 else
306 *pcbData = len;
307 memcpy(pvData, src, len);
309 return ret;
312 static BOOL CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
313 DWORD dwIndex, void *pvData, DWORD *pcbData)
315 CDataEncodeMsg *msg = hCryptMsg;
316 BOOL ret = FALSE;
318 switch (dwParamType)
320 case CMSG_CONTENT_PARAM:
321 if (msg->base.streamed)
322 SetLastError(E_INVALIDARG);
323 else
325 CRYPT_CONTENT_INFO info;
326 char rsa_data[] = "1.2.840.113549.1.7.1";
328 info.pszObjId = rsa_data;
329 info.Content.cbData = msg->bare_content_len;
330 info.Content.pbData = msg->bare_content;
331 ret = CryptEncodeObject(X509_ASN_ENCODING, PKCS_CONTENT_INFO, &info,
332 pvData, pcbData);
334 break;
335 case CMSG_BARE_CONTENT_PARAM:
336 if (msg->base.streamed)
337 SetLastError(E_INVALIDARG);
338 else
339 ret = CRYPT_CopyParam(pvData, pcbData, msg->bare_content,
340 msg->bare_content_len);
341 break;
342 default:
343 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
345 return ret;
348 static HCRYPTMSG CDataEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
349 LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo)
351 CDataEncodeMsg *msg;
353 if (pvMsgEncodeInfo)
355 SetLastError(E_INVALIDARG);
356 return NULL;
358 msg = CryptMemAlloc(sizeof(CDataEncodeMsg));
359 if (msg)
361 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo,
362 CDataEncodeMsg_Close, CDataEncodeMsg_GetParam, CDataEncodeMsg_Update,
363 CRYPT_DefaultMsgControl);
364 msg->bare_content_len = sizeof(empty_data_content);
365 msg->bare_content = (LPBYTE)empty_data_content;
367 return msg;
370 typedef struct _CHashEncodeMsg
372 CryptMsgBase base;
373 HCRYPTPROV prov;
374 HCRYPTHASH hash;
375 CRYPT_DATA_BLOB data;
376 } CHashEncodeMsg;
378 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg)
380 CHashEncodeMsg *msg = hCryptMsg;
382 CryptMemFree(msg->data.pbData);
383 CryptDestroyHash(msg->hash);
384 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
385 CryptReleaseContext(msg->prov, 0);
388 static BOOL CRYPT_EncodePKCSDigestedData(CHashEncodeMsg *msg, void *pvData,
389 DWORD *pcbData)
391 BOOL ret;
392 ALG_ID algID;
393 DWORD size = sizeof(algID);
395 ret = CryptGetHashParam(msg->hash, HP_ALGID, (BYTE *)&algID, &size, 0);
396 if (ret)
398 CRYPT_DIGESTED_DATA digestedData = { 0 };
399 char oid_rsa_data[] = szOID_RSA_data;
401 digestedData.version = CMSG_HASHED_DATA_PKCS_1_5_VERSION;
402 digestedData.DigestAlgorithm.pszObjId = (LPSTR)CertAlgIdToOID(algID);
403 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
404 /* Quirk: OID is only encoded messages if an update has happened */
405 if (msg->base.state != MsgStateInit)
406 digestedData.ContentInfo.pszObjId = oid_rsa_data;
407 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && msg->data.cbData)
409 ret = CRYPT_AsnEncodeOctets(0, NULL, &msg->data,
410 CRYPT_ENCODE_ALLOC_FLAG, NULL,
411 (LPBYTE)&digestedData.ContentInfo.Content.pbData,
412 &digestedData.ContentInfo.Content.cbData);
414 if (msg->base.state == MsgStateFinalized)
416 size = sizeof(DWORD);
417 ret = CryptGetHashParam(msg->hash, HP_HASHSIZE,
418 (LPBYTE)&digestedData.hash.cbData, &size, 0);
419 if (ret)
421 digestedData.hash.pbData = CryptMemAlloc(
422 digestedData.hash.cbData);
423 ret = CryptGetHashParam(msg->hash, HP_HASHVAL,
424 digestedData.hash.pbData, &digestedData.hash.cbData, 0);
427 if (ret)
428 ret = CRYPT_AsnEncodePKCSDigestedData(&digestedData, pvData,
429 pcbData);
430 CryptMemFree(digestedData.hash.pbData);
431 LocalFree(digestedData.ContentInfo.Content.pbData);
433 return ret;
436 static BOOL CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
437 DWORD dwIndex, void *pvData, DWORD *pcbData)
439 CHashEncodeMsg *msg = hCryptMsg;
440 BOOL ret = FALSE;
442 TRACE("(%p, %ld, %ld, %p, %p)\n", hCryptMsg, dwParamType, dwIndex,
443 pvData, pcbData);
445 switch (dwParamType)
447 case CMSG_BARE_CONTENT_PARAM:
448 if (msg->base.streamed)
449 SetLastError(E_INVALIDARG);
450 else
451 ret = CRYPT_EncodePKCSDigestedData(msg, pvData, pcbData);
452 break;
453 case CMSG_CONTENT_PARAM:
455 CRYPT_CONTENT_INFO info;
457 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL,
458 &info.Content.cbData);
459 if (ret)
461 info.Content.pbData = CryptMemAlloc(info.Content.cbData);
462 if (info.Content.pbData)
464 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0,
465 info.Content.pbData, &info.Content.cbData);
466 if (ret)
468 char oid_rsa_hashed[] = szOID_RSA_hashedData;
470 info.pszObjId = oid_rsa_hashed;
471 ret = CryptEncodeObjectEx(X509_ASN_ENCODING,
472 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData);
474 CryptMemFree(info.Content.pbData);
476 else
477 ret = FALSE;
479 break;
481 case CMSG_COMPUTED_HASH_PARAM:
482 ret = CryptGetHashParam(msg->hash, HP_HASHVAL, pvData, pcbData, 0);
483 break;
484 case CMSG_VERSION_PARAM:
485 if (msg->base.state != MsgStateFinalized)
486 SetLastError(CRYPT_E_MSG_ERROR);
487 else
489 DWORD version = CMSG_HASHED_DATA_PKCS_1_5_VERSION;
491 /* Since the data are always encoded as octets, the version is
492 * always 0 (see rfc3852, section 7)
494 ret = CRYPT_CopyParam(pvData, pcbData, &version, sizeof(version));
496 break;
497 default:
498 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
500 return ret;
503 static BOOL CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
504 DWORD cbData, BOOL fFinal)
506 CHashEncodeMsg *msg = hCryptMsg;
507 BOOL ret = FALSE;
509 TRACE("(%p, %p, %ld, %d)\n", hCryptMsg, pbData, cbData, fFinal);
511 if (msg->base.state == MsgStateFinalized)
512 SetLastError(CRYPT_E_MSG_ERROR);
513 else if (msg->base.streamed || (msg->base.open_flags & CMSG_DETACHED_FLAG))
515 /* Doesn't do much, as stream output is never called, and you
516 * can't get the content.
518 ret = CryptHashData(msg->hash, pbData, cbData, 0);
519 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated;
521 else
523 if (!fFinal)
524 SetLastError(CRYPT_E_MSG_ERROR);
525 else
527 ret = CryptHashData(msg->hash, pbData, cbData, 0);
528 if (ret)
530 msg->data.pbData = CryptMemAlloc(cbData);
531 if (msg->data.pbData)
533 memcpy(msg->data.pbData + msg->data.cbData, pbData, cbData);
534 msg->data.cbData += cbData;
536 else
537 ret = FALSE;
539 msg->base.state = MsgStateFinalized;
542 return ret;
545 static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
546 LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo)
548 CHashEncodeMsg *msg;
549 const CMSG_HASHED_ENCODE_INFO *info = pvMsgEncodeInfo;
550 HCRYPTPROV prov;
551 ALG_ID algID;
553 if (info->cbSize != sizeof(CMSG_HASHED_ENCODE_INFO))
555 SetLastError(E_INVALIDARG);
556 return NULL;
558 if (!(algID = CertOIDToAlgId(info->HashAlgorithm.pszObjId)))
560 SetLastError(CRYPT_E_UNKNOWN_ALGO);
561 return NULL;
563 if (info->hCryptProv)
564 prov = info->hCryptProv;
565 else
567 prov = I_CryptGetDefaultCryptProv(algID);
568 if (!prov)
570 SetLastError(E_INVALIDARG);
571 return NULL;
573 dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
575 msg = CryptMemAlloc(sizeof(CHashEncodeMsg));
576 if (msg)
578 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo,
579 CHashEncodeMsg_Close, CHashEncodeMsg_GetParam, CHashEncodeMsg_Update,
580 CRYPT_DefaultMsgControl);
581 msg->prov = prov;
582 msg->data.cbData = 0;
583 msg->data.pbData = NULL;
584 if (!CryptCreateHash(prov, algID, 0, 0, &msg->hash))
586 CryptMsgClose(msg);
587 msg = NULL;
590 return msg;
593 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
595 DWORD cbSize;
596 PCERT_INFO pCertInfo;
597 HCRYPTPROV hCryptProv;
598 DWORD dwKeySpec;
599 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
600 void *pvHashAuxInfo;
601 DWORD cAuthAttr;
602 PCRYPT_ATTRIBUTE rgAuthAttr;
603 DWORD cUnauthAttr;
604 PCRYPT_ATTRIBUTE rgUnauthAttr;
605 CERT_ID SignerId;
606 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
607 void *pvHashEncryptionAuxInfo;
608 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS;
610 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
612 DWORD cbSize;
613 DWORD cSigners;
614 CMSG_SIGNER_ENCODE_INFO_WITH_CMS *rgSigners;
615 DWORD cCertEncoded;
616 PCERT_BLOB rgCertEncoded;
617 DWORD cCrlEncoded;
618 PCRL_BLOB rgCrlEncoded;
619 DWORD cAttrCertEncoded;
620 PCERT_BLOB rgAttrCertEncoded;
621 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS;
623 static BOOL CRYPT_IsValidSigner(const CMSG_SIGNER_ENCODE_INFO_WITH_CMS *signer)
625 if (signer->cbSize != sizeof(CMSG_SIGNER_ENCODE_INFO) &&
626 signer->cbSize != sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS))
628 SetLastError(E_INVALIDARG);
629 return FALSE;
631 if (signer->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO))
633 if (!signer->pCertInfo->SerialNumber.cbData)
635 SetLastError(E_INVALIDARG);
636 return FALSE;
638 if (!signer->pCertInfo->Issuer.cbData)
640 SetLastError(E_INVALIDARG);
641 return FALSE;
644 else if (signer->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS))
646 switch (signer->SignerId.dwIdChoice)
648 case 0:
649 if (!signer->pCertInfo->SerialNumber.cbData)
651 SetLastError(E_INVALIDARG);
652 return FALSE;
654 if (!signer->pCertInfo->Issuer.cbData)
656 SetLastError(E_INVALIDARG);
657 return FALSE;
659 break;
660 case CERT_ID_ISSUER_SERIAL_NUMBER:
661 if (!signer->SignerId.u.IssuerSerialNumber.SerialNumber.cbData)
663 SetLastError(E_INVALIDARG);
664 return FALSE;
666 if (!signer->SignerId.u.IssuerSerialNumber.Issuer.cbData)
668 SetLastError(E_INVALIDARG);
669 return FALSE;
671 break;
672 case CERT_ID_KEY_IDENTIFIER:
673 if (!signer->SignerId.u.KeyId.cbData)
675 SetLastError(E_INVALIDARG);
676 return FALSE;
678 break;
679 default:
680 SetLastError(E_INVALIDARG);
682 if (signer->HashEncryptionAlgorithm.pszObjId)
684 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
685 return FALSE;
688 if (!signer->hCryptProv)
690 SetLastError(E_INVALIDARG);
691 return FALSE;
693 if (!CertOIDToAlgId(signer->HashAlgorithm.pszObjId))
695 SetLastError(CRYPT_E_UNKNOWN_ALGO);
696 return FALSE;
698 return TRUE;
701 static BOOL CRYPT_ConstructBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in)
703 BOOL ret = TRUE;
705 out->cbData = in->cbData;
706 if (out->cbData)
708 out->pbData = CryptMemAlloc(out->cbData);
709 if (out->pbData)
710 memcpy(out->pbData, in->pbData, out->cbData);
711 else
712 ret = FALSE;
714 else
715 out->pbData = NULL;
716 return ret;
719 static BOOL CRYPT_ConstructBlobArray(DWORD *outCBlobs,
720 PCRYPT_DATA_BLOB *outPBlobs, DWORD cBlobs, const CRYPT_DATA_BLOB *pBlobs)
722 BOOL ret = TRUE;
724 *outCBlobs = cBlobs;
725 if (cBlobs)
727 *outPBlobs = CryptMemAlloc(cBlobs * sizeof(CRYPT_DATA_BLOB));
728 if (*outPBlobs)
730 DWORD i;
732 memset(*outPBlobs, 0, cBlobs * sizeof(CRYPT_DATA_BLOB));
733 for (i = 0; ret && i < cBlobs; i++)
734 ret = CRYPT_ConstructBlob(&(*outPBlobs)[i], &pBlobs[i]);
736 else
737 ret = FALSE;
739 return ret;
742 static void CRYPT_FreeBlobArray(DWORD cBlobs, PCRYPT_DATA_BLOB blobs)
744 DWORD i;
746 for (i = 0; i < cBlobs; i++)
747 CryptMemFree(blobs[i].pbData);
748 CryptMemFree(blobs);
751 static BOOL CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE *out,
752 const CRYPT_ATTRIBUTE *in)
754 BOOL ret;
756 out->pszObjId = CryptMemAlloc(strlen(in->pszObjId) + 1);
757 if (out->pszObjId)
759 strcpy(out->pszObjId, in->pszObjId);
760 ret = CRYPT_ConstructBlobArray(&out->cValue, &out->rgValue,
761 in->cValue, in->rgValue);
763 else
764 ret = FALSE;
765 return ret;
768 static BOOL CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES *out,
769 const CRYPT_ATTRIBUTES *in)
771 BOOL ret = TRUE;
773 out->cAttr = in->cAttr;
774 if (out->cAttr)
776 out->rgAttr = CryptMemAlloc(out->cAttr * sizeof(CRYPT_ATTRIBUTE));
777 if (out->rgAttr)
779 DWORD i;
781 memset(out->rgAttr, 0, out->cAttr * sizeof(CRYPT_ATTRIBUTE));
782 for (i = 0; ret && i < out->cAttr; i++)
783 ret = CRYPT_ConstructAttribute(&out->rgAttr[i], &in->rgAttr[i]);
785 else
786 ret = FALSE;
788 else
789 out->rgAttr = NULL;
790 return ret;
793 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
794 static BOOL CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO *info,
795 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS *in)
797 BOOL ret;
799 if (in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO))
801 info->dwVersion = CMSG_SIGNER_INFO_V1;
802 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer,
803 &in->pCertInfo->Issuer);
804 if (ret)
805 ret = CRYPT_ConstructBlob(
806 &info->SignerId.u.IssuerSerialNumber.SerialNumber,
807 &in->pCertInfo->SerialNumber);
808 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
809 info->HashEncryptionAlgorithm.pszObjId =
810 in->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
811 if (ret)
812 ret = CRYPT_ConstructBlob(&info->HashEncryptionAlgorithm.Parameters,
813 &in->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters);
815 else
817 const CRYPT_ALGORITHM_IDENTIFIER *pEncrAlg;
819 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS).
820 * See CRYPT_IsValidSigner.
822 if (!in->SignerId.dwIdChoice)
824 info->dwVersion = CMSG_SIGNER_INFO_V1;
825 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer,
826 &in->pCertInfo->Issuer);
827 if (ret)
828 ret = CRYPT_ConstructBlob(
829 &info->SignerId.u.IssuerSerialNumber.SerialNumber,
830 &in->pCertInfo->SerialNumber);
831 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
833 else if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
835 info->dwVersion = CMSG_SIGNER_INFO_V1;
836 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
837 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer,
838 &in->SignerId.u.IssuerSerialNumber.Issuer);
839 if (ret)
840 ret = CRYPT_ConstructBlob(
841 &info->SignerId.u.IssuerSerialNumber.SerialNumber,
842 &in->SignerId.u.IssuerSerialNumber.SerialNumber);
844 else
846 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */
847 info->dwVersion = CMSG_SIGNER_INFO_V3;
848 info->SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
849 ret = CRYPT_ConstructBlob(&info->SignerId.u.KeyId,
850 &in->SignerId.u.KeyId);
852 pEncrAlg = in->HashEncryptionAlgorithm.pszObjId ?
853 &in->HashEncryptionAlgorithm :
854 &in->pCertInfo->SubjectPublicKeyInfo.Algorithm;
855 info->HashEncryptionAlgorithm.pszObjId = pEncrAlg->pszObjId;
856 if (ret)
857 ret = CRYPT_ConstructBlob(&info->HashEncryptionAlgorithm.Parameters,
858 &pEncrAlg->Parameters);
860 /* Assumption: algorithm IDs will point to static strings, not
861 * stack-based ones, so copying the pointer values is safe.
863 info->HashAlgorithm.pszObjId = in->HashAlgorithm.pszObjId;
864 if (ret)
865 ret = CRYPT_ConstructBlob(&info->HashAlgorithm.Parameters,
866 &in->HashAlgorithm.Parameters);
867 if (ret)
868 ret = CRYPT_ConstructAttributes(&info->AuthAttrs,
869 (CRYPT_ATTRIBUTES *)&in->cAuthAttr);
870 if (ret)
871 ret = CRYPT_ConstructAttributes(&info->UnauthAttrs,
872 (CRYPT_ATTRIBUTES *)&in->cUnauthAttr);
873 return ret;
876 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO *info)
878 DWORD i, j;
880 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
882 CryptMemFree(info->SignerId.u.IssuerSerialNumber.Issuer.pbData);
883 CryptMemFree(info->SignerId.u.IssuerSerialNumber.SerialNumber.pbData);
885 else
886 CryptMemFree(info->SignerId.u.KeyId.pbData);
887 CryptMemFree(info->HashAlgorithm.Parameters.pbData);
888 CryptMemFree(info->HashEncryptionAlgorithm.Parameters.pbData);
889 CryptMemFree(info->EncryptedHash.pbData);
890 for (i = 0; i < info->AuthAttrs.cAttr; i++)
892 for (j = 0; j < info->AuthAttrs.rgAttr[i].cValue; j++)
893 CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue[j].pbData);
894 CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue);
895 CryptMemFree(info->AuthAttrs.rgAttr[i].pszObjId);
897 CryptMemFree(info->AuthAttrs.rgAttr);
898 for (i = 0; i < info->UnauthAttrs.cAttr; i++)
900 for (j = 0; j < info->UnauthAttrs.rgAttr[i].cValue; j++)
901 CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue[j].pbData);
902 CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue);
903 CryptMemFree(info->UnauthAttrs.rgAttr[i].pszObjId);
905 CryptMemFree(info->UnauthAttrs.rgAttr);
908 typedef struct _CSignerHandles
910 HCRYPTHASH contentHash;
911 HCRYPTHASH authAttrHash;
912 } CSignerHandles;
914 typedef struct _CSignedMsgData
916 CRYPT_SIGNED_INFO *info;
917 DWORD cSignerHandle;
918 CSignerHandles *signerHandles;
919 } CSignedMsgData;
921 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
922 * Assumes signerIndex is a valid index, and that msg_data's info has already
923 * been constructed.
925 static BOOL CSignedMsgData_ConstructSignerHandles(CSignedMsgData *msg_data,
926 DWORD signerIndex, HCRYPTPROV *crypt_prov, DWORD *flags)
928 ALG_ID algID;
929 BOOL ret;
931 algID = CertOIDToAlgId(
932 msg_data->info->rgSignerInfo[signerIndex].HashAlgorithm.pszObjId);
934 if (!*crypt_prov)
936 *crypt_prov = I_CryptGetDefaultCryptProv(algID);
937 if (!*crypt_prov) return FALSE;
938 *flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
941 ret = CryptCreateHash(*crypt_prov, algID, 0, 0,
942 &msg_data->signerHandles->contentHash);
943 if (ret && msg_data->info->rgSignerInfo[signerIndex].AuthAttrs.cAttr > 0)
944 ret = CryptCreateHash(*crypt_prov, algID, 0, 0,
945 &msg_data->signerHandles->authAttrHash);
946 return ret;
949 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
950 * constructed.
952 static BOOL CSignedMsgData_AllocateHandles(CSignedMsgData *msg_data)
954 BOOL ret = TRUE;
956 if (msg_data->info->cSignerInfo)
958 msg_data->signerHandles =
959 CryptMemAlloc(msg_data->info->cSignerInfo * sizeof(CSignerHandles));
960 if (msg_data->signerHandles)
962 msg_data->cSignerHandle = msg_data->info->cSignerInfo;
963 memset(msg_data->signerHandles, 0,
964 msg_data->info->cSignerInfo * sizeof(CSignerHandles));
966 else
968 msg_data->cSignerHandle = 0;
969 ret = FALSE;
972 else
974 msg_data->cSignerHandle = 0;
975 msg_data->signerHandles = NULL;
977 return ret;
980 static void CSignedMsgData_CloseHandles(CSignedMsgData *msg_data)
982 DWORD i;
984 for (i = 0; i < msg_data->cSignerHandle; i++)
986 if (msg_data->signerHandles[i].contentHash)
987 CryptDestroyHash(msg_data->signerHandles[i].contentHash);
988 if (msg_data->signerHandles[i].authAttrHash)
989 CryptDestroyHash(msg_data->signerHandles[i].authAttrHash);
991 CryptMemFree(msg_data->signerHandles);
992 msg_data->signerHandles = NULL;
993 msg_data->cSignerHandle = 0;
996 static BOOL CSignedMsgData_UpdateHash(CSignedMsgData *msg_data,
997 const BYTE *pbData, DWORD cbData)
999 DWORD i;
1000 BOOL ret = TRUE;
1002 for (i = 0; ret && i < msg_data->cSignerHandle; i++)
1003 ret = CryptHashData(msg_data->signerHandles[i].contentHash, pbData,
1004 cbData, 0);
1005 return ret;
1008 static BOOL CRYPT_AppendAttribute(CRYPT_ATTRIBUTES *out,
1009 const CRYPT_ATTRIBUTE *in)
1011 BOOL ret = FALSE;
1013 out->rgAttr = CryptMemRealloc(out->rgAttr,
1014 (out->cAttr + 1) * sizeof(CRYPT_ATTRIBUTE));
1015 if (out->rgAttr)
1017 ret = CRYPT_ConstructAttribute(&out->rgAttr[out->cAttr], in);
1018 if (ret)
1019 out->cAttr++;
1021 return ret;
1024 static BOOL CSignedMsgData_AppendMessageDigestAttribute(
1025 CSignedMsgData *msg_data, DWORD signerIndex)
1027 BOOL ret;
1028 DWORD size;
1029 CRYPT_HASH_BLOB hash = { 0, NULL }, encodedHash = { 0, NULL };
1030 char messageDigest[] = szOID_RSA_messageDigest;
1031 CRYPT_ATTRIBUTE messageDigestAttr = { messageDigest, 1, &encodedHash };
1033 size = sizeof(DWORD);
1034 ret = CryptGetHashParam(
1035 msg_data->signerHandles[signerIndex].contentHash, HP_HASHSIZE,
1036 (LPBYTE)&hash.cbData, &size, 0);
1037 if (ret)
1039 hash.pbData = CryptMemAlloc(hash.cbData);
1040 ret = CryptGetHashParam(
1041 msg_data->signerHandles[signerIndex].contentHash, HP_HASHVAL,
1042 hash.pbData, &hash.cbData, 0);
1043 if (ret)
1045 ret = CRYPT_AsnEncodeOctets(0, NULL, &hash, CRYPT_ENCODE_ALLOC_FLAG,
1046 NULL, (LPBYTE)&encodedHash.pbData, &encodedHash.cbData);
1047 if (ret)
1049 ret = CRYPT_AppendAttribute(
1050 &msg_data->info->rgSignerInfo[signerIndex].AuthAttrs,
1051 &messageDigestAttr);
1052 LocalFree(encodedHash.pbData);
1055 CryptMemFree(hash.pbData);
1057 return ret;
1060 typedef enum {
1061 Sign,
1062 Verify
1063 } SignOrVerify;
1065 static BOOL CSignedMsgData_UpdateAuthenticatedAttributes(
1066 CSignedMsgData *msg_data, SignOrVerify flag)
1068 DWORD i;
1069 BOOL ret = TRUE;
1071 TRACE("(%p)\n", msg_data);
1073 for (i = 0; ret && i < msg_data->info->cSignerInfo; i++)
1075 if (msg_data->info->rgSignerInfo[i].AuthAttrs.cAttr)
1077 if (flag == Sign)
1079 BYTE oid_rsa_data_encoded[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
1080 0xf7,0x0d,0x01,0x07,0x01 };
1081 CRYPT_DATA_BLOB content = { sizeof(oid_rsa_data_encoded),
1082 oid_rsa_data_encoded };
1083 char contentType[] = szOID_RSA_contentType;
1084 CRYPT_ATTRIBUTE contentTypeAttr = { contentType, 1, &content };
1086 /* FIXME: does this depend on inner OID? */
1087 ret = CRYPT_AppendAttribute(
1088 &msg_data->info->rgSignerInfo[i].AuthAttrs, &contentTypeAttr);
1089 if (ret)
1090 ret = CSignedMsgData_AppendMessageDigestAttribute(msg_data,
1093 if (ret)
1095 LPBYTE encodedAttrs;
1096 DWORD size;
1098 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, PKCS_ATTRIBUTES,
1099 &msg_data->info->rgSignerInfo[i].AuthAttrs,
1100 CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedAttrs, &size);
1101 if (ret)
1103 ret = CryptHashData(
1104 msg_data->signerHandles[i].authAttrHash, encodedAttrs,
1105 size, 0);
1106 LocalFree(encodedAttrs);
1111 TRACE("returning %d\n", ret);
1112 return ret;
1115 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB *hash)
1117 DWORD i;
1118 BYTE tmp;
1120 for (i = 0; i < hash->cbData / 2; i++)
1122 tmp = hash->pbData[hash->cbData - i - 1];
1123 hash->pbData[hash->cbData - i - 1] = hash->pbData[i];
1124 hash->pbData[i] = tmp;
1128 static BOOL CSignedMsgData_Sign(CSignedMsgData *msg_data)
1130 DWORD i;
1131 BOOL ret = TRUE;
1133 TRACE("(%p)\n", msg_data);
1135 for (i = 0; ret && i < msg_data->info->cSignerInfo; i++)
1137 HCRYPTHASH hash;
1138 DWORD keySpec = msg_data->info->signerKeySpec[i];
1140 if (!keySpec)
1141 keySpec = AT_SIGNATURE;
1142 if (msg_data->info->rgSignerInfo[i].AuthAttrs.cAttr)
1143 hash = msg_data->signerHandles[i].authAttrHash;
1144 else
1145 hash = msg_data->signerHandles[i].contentHash;
1146 ret = CryptSignHashW(hash, keySpec, NULL, 0, NULL,
1147 &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData);
1148 if (ret)
1150 msg_data->info->rgSignerInfo[i].EncryptedHash.pbData =
1151 CryptMemAlloc(
1152 msg_data->info->rgSignerInfo[i].EncryptedHash.cbData);
1153 if (msg_data->info->rgSignerInfo[i].EncryptedHash.pbData)
1155 ret = CryptSignHashW(hash, keySpec, NULL, 0,
1156 msg_data->info->rgSignerInfo[i].EncryptedHash.pbData,
1157 &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData);
1158 if (ret)
1159 CRYPT_ReverseBytes(
1160 &msg_data->info->rgSignerInfo[i].EncryptedHash);
1162 else
1163 ret = FALSE;
1166 return ret;
1169 static BOOL CSignedMsgData_Update(CSignedMsgData *msg_data,
1170 const BYTE *pbData, DWORD cbData, BOOL fFinal, SignOrVerify flag)
1172 BOOL ret = CSignedMsgData_UpdateHash(msg_data, pbData, cbData);
1174 if (ret && fFinal)
1176 ret = CSignedMsgData_UpdateAuthenticatedAttributes(msg_data, flag);
1177 if (ret && flag == Sign)
1178 ret = CSignedMsgData_Sign(msg_data);
1180 return ret;
1183 typedef struct _CSignedEncodeMsg
1185 CryptMsgBase base;
1186 LPSTR innerOID;
1187 CRYPT_DATA_BLOB data;
1188 CSignedMsgData msg_data;
1189 } CSignedEncodeMsg;
1191 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg)
1193 CSignedEncodeMsg *msg = hCryptMsg;
1194 DWORD i;
1196 CryptMemFree(msg->innerOID);
1197 CryptMemFree(msg->data.pbData);
1198 CRYPT_FreeBlobArray(msg->msg_data.info->cCertEncoded,
1199 msg->msg_data.info->rgCertEncoded);
1200 CRYPT_FreeBlobArray(msg->msg_data.info->cCrlEncoded,
1201 msg->msg_data.info->rgCrlEncoded);
1202 for (i = 0; i < msg->msg_data.info->cSignerInfo; i++)
1203 CSignerInfo_Free(&msg->msg_data.info->rgSignerInfo[i]);
1204 CSignedMsgData_CloseHandles(&msg->msg_data);
1205 CryptMemFree(msg->msg_data.info->signerKeySpec);
1206 CryptMemFree(msg->msg_data.info->rgSignerInfo);
1207 CryptMemFree(msg->msg_data.info);
1210 static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
1211 DWORD dwIndex, void *pvData, DWORD *pcbData)
1213 CSignedEncodeMsg *msg = hCryptMsg;
1214 BOOL ret = FALSE;
1216 switch (dwParamType)
1218 case CMSG_CONTENT_PARAM:
1220 CRYPT_CONTENT_INFO info;
1222 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL,
1223 &info.Content.cbData);
1224 if (ret)
1226 info.Content.pbData = CryptMemAlloc(info.Content.cbData);
1227 if (info.Content.pbData)
1229 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0,
1230 info.Content.pbData, &info.Content.cbData);
1231 if (ret)
1233 char oid_rsa_signed[] = szOID_RSA_signedData;
1235 info.pszObjId = oid_rsa_signed;
1236 ret = CryptEncodeObjectEx(X509_ASN_ENCODING,
1237 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData);
1239 CryptMemFree(info.Content.pbData);
1241 else
1242 ret = FALSE;
1244 break;
1246 case CMSG_BARE_CONTENT_PARAM:
1248 CRYPT_SIGNED_INFO info;
1249 BOOL freeContent = FALSE;
1251 info = *msg->msg_data.info;
1252 if (!msg->innerOID || !strcmp(msg->innerOID, szOID_RSA_data))
1254 char oid_rsa_data[] = szOID_RSA_data;
1256 /* Quirk: OID is only encoded messages if an update has happened */
1257 if (msg->base.state != MsgStateInit)
1258 info.content.pszObjId = oid_rsa_data;
1259 else
1260 info.content.pszObjId = NULL;
1261 if (msg->data.cbData)
1263 CRYPT_DATA_BLOB blob = { msg->data.cbData, msg->data.pbData };
1265 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
1266 &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL,
1267 &info.content.Content.pbData, &info.content.Content.cbData);
1268 freeContent = TRUE;
1270 else
1272 info.content.Content.cbData = 0;
1273 info.content.Content.pbData = NULL;
1274 ret = TRUE;
1277 else
1279 info.content.pszObjId = msg->innerOID;
1280 info.content.Content.cbData = msg->data.cbData;
1281 info.content.Content.pbData = msg->data.pbData;
1282 ret = TRUE;
1284 if (ret)
1286 ret = CRYPT_AsnEncodeCMSSignedInfo(&info, pvData, pcbData);
1287 if (freeContent)
1288 LocalFree(info.content.Content.pbData);
1290 break;
1292 case CMSG_COMPUTED_HASH_PARAM:
1293 if (dwIndex >= msg->msg_data.cSignerHandle)
1294 SetLastError(CRYPT_E_INVALID_INDEX);
1295 else
1296 ret = CryptGetHashParam(
1297 msg->msg_data.signerHandles[dwIndex].contentHash, HP_HASHVAL,
1298 pvData, pcbData, 0);
1299 break;
1300 case CMSG_ENCODED_SIGNER:
1301 if (dwIndex >= msg->msg_data.info->cSignerInfo)
1302 SetLastError(CRYPT_E_INVALID_INDEX);
1303 else
1304 ret = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1305 CMS_SIGNER_INFO, &msg->msg_data.info->rgSignerInfo[dwIndex], 0,
1306 NULL, pvData, pcbData);
1307 break;
1308 case CMSG_VERSION_PARAM:
1309 ret = CRYPT_CopyParam(pvData, pcbData, &msg->msg_data.info->version,
1310 sizeof(msg->msg_data.info->version));
1311 break;
1312 default:
1313 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
1315 return ret;
1318 static BOOL CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
1319 DWORD cbData, BOOL fFinal)
1321 CSignedEncodeMsg *msg = hCryptMsg;
1322 BOOL ret = FALSE;
1324 if (msg->base.state == MsgStateFinalized)
1325 SetLastError(CRYPT_E_MSG_ERROR);
1326 else if (msg->base.streamed || (msg->base.open_flags & CMSG_DETACHED_FLAG))
1328 ret = CSignedMsgData_Update(&msg->msg_data, pbData, cbData, fFinal,
1329 Sign);
1330 if (msg->base.streamed)
1331 FIXME("streamed partial stub\n");
1332 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated;
1334 else
1336 if (!fFinal)
1337 SetLastError(CRYPT_E_MSG_ERROR);
1338 else
1340 if (cbData)
1342 msg->data.pbData = CryptMemAlloc(cbData);
1343 if (msg->data.pbData)
1345 memcpy(msg->data.pbData, pbData, cbData);
1346 msg->data.cbData = cbData;
1347 ret = TRUE;
1350 else
1351 ret = TRUE;
1352 if (ret)
1353 ret = CSignedMsgData_Update(&msg->msg_data, pbData, cbData,
1354 fFinal, Sign);
1355 msg->base.state = MsgStateFinalized;
1358 return ret;
1361 static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags,
1362 const void *pvMsgEncodeInfo, LPCSTR pszInnerContentObjID,
1363 PCMSG_STREAM_INFO pStreamInfo)
1365 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS *info = pvMsgEncodeInfo;
1366 DWORD i;
1367 CSignedEncodeMsg *msg;
1369 if (info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO) &&
1370 info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS))
1372 SetLastError(E_INVALIDARG);
1373 return NULL;
1375 if (info->cbSize == sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS) &&
1376 info->cAttrCertEncoded)
1378 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1379 return NULL;
1381 for (i = 0; i < info->cSigners; i++)
1382 if (!CRYPT_IsValidSigner(&info->rgSigners[i]))
1383 return NULL;
1384 msg = CryptMemAlloc(sizeof(CSignedEncodeMsg));
1385 if (msg)
1387 BOOL ret = TRUE;
1389 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo,
1390 CSignedEncodeMsg_Close, CSignedEncodeMsg_GetParam,
1391 CSignedEncodeMsg_Update, CRYPT_DefaultMsgControl);
1392 if (pszInnerContentObjID)
1394 msg->innerOID = CryptMemAlloc(strlen(pszInnerContentObjID) + 1);
1395 if (msg->innerOID)
1396 strcpy(msg->innerOID, pszInnerContentObjID);
1397 else
1398 ret = FALSE;
1400 else
1401 msg->innerOID = NULL;
1402 msg->data.cbData = 0;
1403 msg->data.pbData = NULL;
1404 if (ret)
1405 msg->msg_data.info = CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO));
1406 else
1407 msg->msg_data.info = NULL;
1408 if (msg->msg_data.info)
1410 memset(msg->msg_data.info, 0, sizeof(CRYPT_SIGNED_INFO));
1411 msg->msg_data.info->version = CMSG_SIGNED_DATA_V1;
1413 else
1414 ret = FALSE;
1415 if (ret)
1417 if (info->cSigners)
1419 msg->msg_data.info->rgSignerInfo =
1420 CryptMemAlloc(info->cSigners * sizeof(CMSG_CMS_SIGNER_INFO));
1421 if (msg->msg_data.info->rgSignerInfo)
1423 msg->msg_data.info->cSignerInfo = info->cSigners;
1424 memset(msg->msg_data.info->rgSignerInfo, 0,
1425 msg->msg_data.info->cSignerInfo *
1426 sizeof(CMSG_CMS_SIGNER_INFO));
1427 ret = CSignedMsgData_AllocateHandles(&msg->msg_data);
1428 msg->msg_data.info->signerKeySpec = CryptMemAlloc(info->cSigners * sizeof(DWORD));
1429 if (!msg->msg_data.info->signerKeySpec)
1430 ret = FALSE;
1431 for (i = 0; ret && i < msg->msg_data.info->cSignerInfo; i++)
1433 if (info->rgSigners[i].SignerId.dwIdChoice ==
1434 CERT_ID_KEY_IDENTIFIER)
1435 msg->msg_data.info->version = CMSG_SIGNED_DATA_V3;
1436 ret = CSignerInfo_Construct(
1437 &msg->msg_data.info->rgSignerInfo[i],
1438 &info->rgSigners[i]);
1439 if (ret)
1441 ret = CSignedMsgData_ConstructSignerHandles(
1442 &msg->msg_data, i, &info->rgSigners[i].hCryptProv, &dwFlags);
1443 if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
1444 CryptReleaseContext(info->rgSigners[i].hCryptProv,
1447 msg->msg_data.info->signerKeySpec[i] =
1448 info->rgSigners[i].dwKeySpec;
1451 else
1452 ret = FALSE;
1454 else
1456 msg->msg_data.info->cSignerInfo = 0;
1457 msg->msg_data.signerHandles = NULL;
1458 msg->msg_data.cSignerHandle = 0;
1461 if (ret)
1462 ret = CRYPT_ConstructBlobArray(&msg->msg_data.info->cCertEncoded,
1463 &msg->msg_data.info->rgCertEncoded, info->cCertEncoded,
1464 info->rgCertEncoded);
1465 if (ret)
1466 ret = CRYPT_ConstructBlobArray(&msg->msg_data.info->cCrlEncoded,
1467 &msg->msg_data.info->rgCrlEncoded, info->cCrlEncoded,
1468 info->rgCrlEncoded);
1469 if (!ret)
1471 CSignedEncodeMsg_Close(msg);
1472 CryptMemFree(msg);
1473 msg = NULL;
1476 return msg;
1479 typedef struct _CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
1481 DWORD cbSize;
1482 HCRYPTPROV_LEGACY hCryptProv;
1483 CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm;
1484 void *pvEncryptionAuxInfo;
1485 DWORD cRecipients;
1486 PCERT_INFO *rgpRecipientCert;
1487 PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients;
1488 DWORD cCertEncoded;
1489 PCERT_BLOB rgCertEncoded;
1490 DWORD cCrlEncoded;
1491 PCRL_BLOB rgCrlEncoded;
1492 DWORD cAttrCertEncoded;
1493 PCERT_BLOB rgAttrCertEncoded;
1494 DWORD cUnprotectedAttr;
1495 PCRYPT_ATTRIBUTE rgUnprotectedAttr;
1496 } CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS;
1498 typedef struct _CEnvelopedEncodeMsg
1500 CryptMsgBase base;
1501 CRYPT_ALGORITHM_IDENTIFIER algo;
1502 HCRYPTPROV prov;
1503 HCRYPTKEY key;
1504 DWORD cRecipientInfo;
1505 CMSG_KEY_TRANS_RECIPIENT_INFO *recipientInfo;
1506 CRYPT_DATA_BLOB data;
1507 } CEnvelopedEncodeMsg;
1509 static BOOL CRYPT_ConstructAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER *out,
1510 const CRYPT_ALGORITHM_IDENTIFIER *in)
1512 out->pszObjId = CryptMemAlloc(strlen(in->pszObjId) + 1);
1513 if (out->pszObjId)
1515 strcpy(out->pszObjId, in->pszObjId);
1516 return CRYPT_ConstructBlob(&out->Parameters, &in->Parameters);
1518 else
1519 return FALSE;
1522 static BOOL CRYPT_ConstructBitBlob(CRYPT_BIT_BLOB *out, const CRYPT_BIT_BLOB *in)
1524 out->cbData = in->cbData;
1525 out->cUnusedBits = in->cUnusedBits;
1526 if (out->cbData)
1528 out->pbData = CryptMemAlloc(out->cbData);
1529 if (out->pbData)
1530 memcpy(out->pbData, in->pbData, out->cbData);
1531 else
1532 return FALSE;
1534 else
1535 out->pbData = NULL;
1536 return TRUE;
1539 static BOOL CRYPT_GenKey(CMSG_CONTENT_ENCRYPT_INFO *info, ALG_ID algID)
1541 static HCRYPTOIDFUNCSET set = NULL;
1542 PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY genKeyFunc = NULL;
1543 HCRYPTOIDFUNCADDR hFunc;
1544 BOOL ret;
1546 if (!set)
1547 set = CryptInitOIDFunctionSet(CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC, 0);
1548 CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING,
1549 info->ContentEncryptionAlgorithm.pszObjId, 0, (void **)&genKeyFunc, &hFunc);
1550 if (genKeyFunc)
1552 ret = genKeyFunc(info, 0, NULL);
1553 CryptFreeOIDFunctionAddress(hFunc, 0);
1555 else
1556 ret = CryptGenKey(info->hCryptProv, algID, CRYPT_EXPORTABLE,
1557 &info->hContentEncryptKey);
1558 return ret;
1561 static BOOL WINAPI CRYPT_ExportKeyTrans(
1562 PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
1563 PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo,
1564 PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo,
1565 DWORD dwFlags, void *pvReserved)
1567 CERT_PUBLIC_KEY_INFO keyInfo;
1568 HCRYPTKEY expKey;
1569 BOOL ret;
1571 ret = CRYPT_ConstructAlgorithmId(&keyInfo.Algorithm,
1572 &pKeyTransEncodeInfo->KeyEncryptionAlgorithm);
1573 if (ret)
1574 ret = CRYPT_ConstructBitBlob(&keyInfo.PublicKey,
1575 &pKeyTransEncodeInfo->RecipientPublicKey);
1576 if (ret)
1577 ret = CryptImportPublicKeyInfo(pKeyTransEncodeInfo->hCryptProv,
1578 X509_ASN_ENCODING, &keyInfo, &expKey);
1579 if (ret)
1581 DWORD size;
1583 ret = CryptExportKey(pContentEncryptInfo->hContentEncryptKey, expKey,
1584 SIMPLEBLOB, 0, NULL, &size);
1585 if (ret)
1587 BYTE *keyBlob;
1589 keyBlob = CryptMemAlloc(size);
1590 if (keyBlob)
1592 ret = CryptExportKey(pContentEncryptInfo->hContentEncryptKey,
1593 expKey, SIMPLEBLOB, 0, keyBlob, &size);
1594 if (ret)
1596 DWORD head = sizeof(BLOBHEADER) + sizeof(ALG_ID);
1598 pKeyTransEncryptInfo->EncryptedKey.pbData =
1599 CryptMemAlloc(size - head);
1600 if (pKeyTransEncryptInfo->EncryptedKey.pbData)
1602 DWORD i, k = 0;
1604 pKeyTransEncryptInfo->EncryptedKey.cbData = size - head;
1605 for (i = size - 1; i >= head; --i, ++k)
1606 pKeyTransEncryptInfo->EncryptedKey.pbData[k] =
1607 keyBlob[i];
1609 else
1610 ret = FALSE;
1612 CryptMemFree(keyBlob);
1614 else
1615 ret = FALSE;
1617 CryptDestroyKey(expKey);
1620 CryptMemFree(keyInfo.PublicKey.pbData);
1621 CryptMemFree(keyInfo.Algorithm.pszObjId);
1622 CryptMemFree(keyInfo.Algorithm.Parameters.pbData);
1623 return ret;
1626 static BOOL CRYPT_ExportEncryptedKey(CMSG_CONTENT_ENCRYPT_INFO *info, DWORD i,
1627 CRYPT_DATA_BLOB *key)
1629 static HCRYPTOIDFUNCSET set = NULL;
1630 PFN_CMSG_EXPORT_KEY_TRANS exportKeyFunc = NULL;
1631 HCRYPTOIDFUNCADDR hFunc = NULL;
1632 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *encodeInfo =
1633 info->rgCmsRecipients[i].u.pKeyTrans;
1634 CMSG_KEY_TRANS_ENCRYPT_INFO encryptInfo;
1635 BOOL ret;
1637 memset(&encryptInfo, 0, sizeof(encryptInfo));
1638 encryptInfo.cbSize = sizeof(encryptInfo);
1639 encryptInfo.dwRecipientIndex = i;
1640 ret = CRYPT_ConstructAlgorithmId(&encryptInfo.KeyEncryptionAlgorithm,
1641 &encodeInfo->KeyEncryptionAlgorithm);
1643 if (!set)
1644 set = CryptInitOIDFunctionSet(CMSG_OID_EXPORT_KEY_TRANS_FUNC, 0);
1645 CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING,
1646 encryptInfo.KeyEncryptionAlgorithm.pszObjId, 0, (void **)&exportKeyFunc,
1647 &hFunc);
1648 if (!exportKeyFunc)
1649 exportKeyFunc = CRYPT_ExportKeyTrans;
1650 if (ret)
1652 ret = exportKeyFunc(info, encodeInfo, &encryptInfo, 0, NULL);
1653 if (ret)
1655 key->cbData = encryptInfo.EncryptedKey.cbData;
1656 key->pbData = encryptInfo.EncryptedKey.pbData;
1659 if (hFunc)
1660 CryptFreeOIDFunctionAddress(hFunc, 0);
1662 CryptMemFree(encryptInfo.KeyEncryptionAlgorithm.pszObjId);
1663 CryptMemFree(encryptInfo.KeyEncryptionAlgorithm.Parameters.pbData);
1664 return ret;
1667 static LPVOID WINAPI mem_alloc(size_t size)
1669 return CryptMemAlloc(size);
1672 static VOID WINAPI mem_free(LPVOID pv)
1674 CryptMemFree(pv);
1678 static BOOL CContentEncryptInfo_Construct(CMSG_CONTENT_ENCRYPT_INFO *info,
1679 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS *in, HCRYPTPROV prov)
1681 BOOL ret;
1683 info->cbSize = sizeof(CMSG_CONTENT_ENCRYPT_INFO);
1684 info->hCryptProv = prov;
1685 ret = CRYPT_ConstructAlgorithmId(&info->ContentEncryptionAlgorithm,
1686 &in->ContentEncryptionAlgorithm);
1687 info->pvEncryptionAuxInfo = in->pvEncryptionAuxInfo;
1688 info->cRecipients = in->cRecipients;
1689 if (ret)
1691 info->rgCmsRecipients = CryptMemAlloc(in->cRecipients *
1692 sizeof(CMSG_RECIPIENT_ENCODE_INFO));
1693 if (info->rgCmsRecipients)
1695 DWORD i;
1697 for (i = 0; ret && i < in->cRecipients; ++i)
1699 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *encodeInfo;
1700 CERT_INFO *cert = in->rgpRecipientCert[i];
1702 info->rgCmsRecipients[i].dwRecipientChoice =
1703 CMSG_KEY_TRANS_RECIPIENT;
1704 encodeInfo = CryptMemAlloc(sizeof(*encodeInfo));
1705 info->rgCmsRecipients[i].u.pKeyTrans = encodeInfo;
1706 if (encodeInfo)
1708 encodeInfo->cbSize = sizeof(*encodeInfo);
1709 ret = CRYPT_ConstructAlgorithmId(
1710 &encodeInfo->KeyEncryptionAlgorithm,
1711 &cert->SubjectPublicKeyInfo.Algorithm);
1712 encodeInfo->pvKeyEncryptionAuxInfo = NULL;
1713 encodeInfo->hCryptProv = prov;
1714 if (ret)
1715 ret = CRYPT_ConstructBitBlob(
1716 &encodeInfo->RecipientPublicKey,
1717 &cert->SubjectPublicKeyInfo.PublicKey);
1718 if (ret)
1719 ret = CRYPT_ConstructBlob(
1720 &encodeInfo->RecipientId.u.IssuerSerialNumber.Issuer,
1721 &cert->Issuer);
1722 if (ret)
1723 ret = CRYPT_ConstructBlob(
1724 &encodeInfo->RecipientId.u.IssuerSerialNumber.SerialNumber,
1725 &cert->SerialNumber);
1727 else
1728 ret = FALSE;
1731 else
1732 ret = FALSE;
1734 info->pfnAlloc = mem_alloc;
1735 info->pfnFree = mem_free;
1736 return ret;
1739 static void CContentEncryptInfo_Free(CMSG_CONTENT_ENCRYPT_INFO *info)
1741 CryptMemFree(info->ContentEncryptionAlgorithm.pszObjId);
1742 CryptMemFree(info->ContentEncryptionAlgorithm.Parameters.pbData);
1743 if (info->rgCmsRecipients)
1745 DWORD i;
1747 for (i = 0; i < info->cRecipients; ++i)
1749 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *encodeInfo =
1750 info->rgCmsRecipients[i].u.pKeyTrans;
1752 CryptMemFree(encodeInfo->KeyEncryptionAlgorithm.pszObjId);
1753 CryptMemFree(encodeInfo->KeyEncryptionAlgorithm.Parameters.pbData);
1754 CryptMemFree(encodeInfo->RecipientPublicKey.pbData);
1755 CryptMemFree(
1756 encodeInfo->RecipientId.u.IssuerSerialNumber.Issuer.pbData);
1757 CryptMemFree(
1758 encodeInfo->RecipientId.u.IssuerSerialNumber.SerialNumber.pbData);
1759 CryptMemFree(encodeInfo);
1761 CryptMemFree(info->rgCmsRecipients);
1765 static BOOL CRecipientInfo_Construct(CMSG_KEY_TRANS_RECIPIENT_INFO *info,
1766 const CERT_INFO *cert, CRYPT_DATA_BLOB *key)
1768 BOOL ret;
1770 info->dwVersion = CMSG_KEY_TRANS_PKCS_1_5_VERSION;
1771 info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
1772 ret = CRYPT_ConstructBlob(&info->RecipientId.u.IssuerSerialNumber.Issuer,
1773 &cert->Issuer);
1774 if (ret)
1775 ret = CRYPT_ConstructBlob(
1776 &info->RecipientId.u.IssuerSerialNumber.SerialNumber,
1777 &cert->SerialNumber);
1778 if (ret)
1779 ret = CRYPT_ConstructAlgorithmId(&info->KeyEncryptionAlgorithm,
1780 &cert->SubjectPublicKeyInfo.Algorithm);
1781 info->EncryptedKey.cbData = key->cbData;
1782 info->EncryptedKey.pbData = key->pbData;
1783 return ret;
1786 static void CRecipientInfo_Free(CMSG_KEY_TRANS_RECIPIENT_INFO *info)
1788 CryptMemFree(info->RecipientId.u.IssuerSerialNumber.Issuer.pbData);
1789 CryptMemFree(info->RecipientId.u.IssuerSerialNumber.SerialNumber.pbData);
1790 CryptMemFree(info->KeyEncryptionAlgorithm.pszObjId);
1791 CryptMemFree(info->KeyEncryptionAlgorithm.Parameters.pbData);
1792 CryptMemFree(info->EncryptedKey.pbData);
1795 static void CEnvelopedEncodeMsg_Close(HCRYPTMSG hCryptMsg)
1797 CEnvelopedEncodeMsg *msg = hCryptMsg;
1799 CryptMemFree(msg->algo.pszObjId);
1800 CryptMemFree(msg->algo.Parameters.pbData);
1801 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
1802 CryptReleaseContext(msg->prov, 0);
1803 CryptDestroyKey(msg->key);
1804 if (msg->recipientInfo)
1806 DWORD i;
1808 for (i = 0; i < msg->cRecipientInfo; ++i)
1809 CRecipientInfo_Free(&msg->recipientInfo[i]);
1810 CryptMemFree(msg->recipientInfo);
1812 CryptMemFree(msg->data.pbData);
1815 static BOOL CEnvelopedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
1816 DWORD dwIndex, void *pvData, DWORD *pcbData)
1818 CEnvelopedEncodeMsg *msg = hCryptMsg;
1819 BOOL ret = FALSE;
1821 switch (dwParamType)
1823 case CMSG_BARE_CONTENT_PARAM:
1824 if (msg->base.streamed)
1825 SetLastError(E_INVALIDARG);
1826 else
1828 char oid_rsa_data[] = szOID_RSA_data;
1829 CRYPT_ENVELOPED_DATA envelopedData = {
1830 CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION, msg->cRecipientInfo,
1831 msg->recipientInfo, { oid_rsa_data, {
1832 msg->algo.pszObjId,
1833 { msg->algo.Parameters.cbData, msg->algo.Parameters.pbData }
1835 { msg->data.cbData, msg->data.pbData }
1839 ret = CRYPT_AsnEncodePKCSEnvelopedData(&envelopedData, pvData,
1840 pcbData);
1842 break;
1843 case CMSG_CONTENT_PARAM:
1845 CRYPT_CONTENT_INFO info;
1847 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL,
1848 &info.Content.cbData);
1849 if (ret)
1851 info.Content.pbData = CryptMemAlloc(info.Content.cbData);
1852 if (info.Content.pbData)
1854 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0,
1855 info.Content.pbData, &info.Content.cbData);
1856 if (ret)
1858 char oid_rsa_enveloped[] = szOID_RSA_envelopedData;
1860 info.pszObjId = oid_rsa_enveloped;
1861 ret = CryptEncodeObjectEx(X509_ASN_ENCODING,
1862 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData);
1864 CryptMemFree(info.Content.pbData);
1866 else
1867 ret = FALSE;
1869 break;
1871 default:
1872 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
1874 return ret;
1877 static BOOL CEnvelopedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
1878 DWORD cbData, BOOL fFinal)
1880 CEnvelopedEncodeMsg *msg = hCryptMsg;
1881 BOOL ret = FALSE;
1883 if (msg->base.state == MsgStateFinalized)
1884 SetLastError(CRYPT_E_MSG_ERROR);
1885 else if (msg->base.streamed)
1887 FIXME("streamed stub\n");
1888 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated;
1889 ret = TRUE;
1891 else
1893 if (!fFinal)
1895 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
1896 SetLastError(E_INVALIDARG);
1897 else
1898 SetLastError(CRYPT_E_MSG_ERROR);
1900 else
1902 if (cbData)
1904 DWORD dataLen = cbData;
1906 msg->data.cbData = cbData;
1907 msg->data.pbData = CryptMemAlloc(cbData);
1908 if (msg->data.pbData)
1910 memcpy(msg->data.pbData, pbData, cbData);
1911 ret = CryptEncrypt(msg->key, 0, TRUE, 0, msg->data.pbData,
1912 &dataLen, msg->data.cbData);
1913 msg->data.cbData = dataLen;
1914 if (dataLen > cbData)
1916 msg->data.pbData = CryptMemRealloc(msg->data.pbData,
1917 dataLen);
1918 if (msg->data.pbData)
1920 dataLen = cbData;
1921 ret = CryptEncrypt(msg->key, 0, TRUE, 0,
1922 msg->data.pbData, &dataLen, msg->data.cbData);
1924 else
1925 ret = FALSE;
1927 if (!ret)
1928 CryptMemFree(msg->data.pbData);
1930 else
1931 ret = FALSE;
1932 if (!ret)
1934 msg->data.cbData = 0;
1935 msg->data.pbData = NULL;
1938 else
1939 ret = TRUE;
1940 msg->base.state = MsgStateFinalized;
1943 return ret;
1946 static HCRYPTMSG CEnvelopedEncodeMsg_Open(DWORD dwFlags,
1947 const void *pvMsgEncodeInfo, LPCSTR pszInnerContentObjID,
1948 PCMSG_STREAM_INFO pStreamInfo)
1950 CEnvelopedEncodeMsg *msg;
1951 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS *info = pvMsgEncodeInfo;
1952 HCRYPTPROV prov;
1953 ALG_ID algID;
1955 if (info->cbSize != sizeof(CMSG_ENVELOPED_ENCODE_INFO) &&
1956 info->cbSize != sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS))
1958 SetLastError(E_INVALIDARG);
1959 return NULL;
1961 if (info->cbSize == sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS))
1962 FIXME("CMS fields unsupported\n");
1963 if (!(algID = CertOIDToAlgId(info->ContentEncryptionAlgorithm.pszObjId)))
1965 SetLastError(CRYPT_E_UNKNOWN_ALGO);
1966 return NULL;
1968 if (info->cRecipients && !info->rgpRecipientCert)
1970 SetLastError(E_INVALIDARG);
1971 return NULL;
1973 if (info->hCryptProv)
1974 prov = info->hCryptProv;
1975 else
1977 prov = I_CryptGetDefaultCryptProv(0);
1978 dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
1980 msg = CryptMemAlloc(sizeof(CEnvelopedEncodeMsg));
1981 if (msg)
1983 CRYPT_DATA_BLOB encryptedKey = { 0, NULL };
1984 CMSG_CONTENT_ENCRYPT_INFO encryptInfo;
1985 BOOL ret;
1986 DWORD i;
1988 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo,
1989 CEnvelopedEncodeMsg_Close, CEnvelopedEncodeMsg_GetParam,
1990 CEnvelopedEncodeMsg_Update, CRYPT_DefaultMsgControl);
1991 ret = CRYPT_ConstructAlgorithmId(&msg->algo,
1992 &info->ContentEncryptionAlgorithm);
1993 msg->prov = prov;
1994 msg->data.cbData = 0;
1995 msg->data.pbData = NULL;
1996 msg->cRecipientInfo = info->cRecipients;
1997 msg->recipientInfo = CryptMemAlloc(info->cRecipients *
1998 sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO));
1999 if (!msg->recipientInfo)
2000 ret = FALSE;
2001 memset(&encryptInfo, 0, sizeof(encryptInfo));
2002 if (ret)
2004 ret = CContentEncryptInfo_Construct(&encryptInfo, info, prov);
2005 if (ret)
2007 ret = CRYPT_GenKey(&encryptInfo, algID);
2008 if (ret)
2009 msg->key = encryptInfo.hContentEncryptKey;
2012 for (i = 0; ret && i < msg->cRecipientInfo; ++i)
2014 ret = CRYPT_ExportEncryptedKey(&encryptInfo, i, &encryptedKey);
2015 if (ret)
2016 ret = CRecipientInfo_Construct(&msg->recipientInfo[i],
2017 info->rgpRecipientCert[i], &encryptedKey);
2019 CContentEncryptInfo_Free(&encryptInfo);
2020 if (!ret)
2022 CryptMsgClose(msg);
2023 msg = NULL;
2026 if (!msg && (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG))
2027 CryptReleaseContext(prov, 0);
2028 return msg;
2031 HCRYPTMSG WINAPI CryptMsgOpenToEncode(DWORD dwMsgEncodingType, DWORD dwFlags,
2032 DWORD dwMsgType, const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID,
2033 PCMSG_STREAM_INFO pStreamInfo)
2035 HCRYPTMSG msg = NULL;
2037 TRACE("(%08lx, %08lx, %08lx, %p, %s, %p)\n", dwMsgEncodingType, dwFlags,
2038 dwMsgType, pvMsgEncodeInfo, debugstr_a(pszInnerContentObjID), pStreamInfo);
2040 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING)
2042 SetLastError(E_INVALIDARG);
2043 return NULL;
2045 switch (dwMsgType)
2047 case CMSG_DATA:
2048 msg = CDataEncodeMsg_Open(dwFlags, pvMsgEncodeInfo,
2049 pszInnerContentObjID, pStreamInfo);
2050 break;
2051 case CMSG_HASHED:
2052 msg = CHashEncodeMsg_Open(dwFlags, pvMsgEncodeInfo,
2053 pszInnerContentObjID, pStreamInfo);
2054 break;
2055 case CMSG_SIGNED:
2056 msg = CSignedEncodeMsg_Open(dwFlags, pvMsgEncodeInfo,
2057 pszInnerContentObjID, pStreamInfo);
2058 break;
2059 case CMSG_ENVELOPED:
2060 msg = CEnvelopedEncodeMsg_Open(dwFlags, pvMsgEncodeInfo,
2061 pszInnerContentObjID, pStreamInfo);
2062 break;
2063 case CMSG_SIGNED_AND_ENVELOPED:
2064 case CMSG_ENCRYPTED:
2065 /* defined but invalid, fall through */
2066 default:
2067 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2069 return msg;
2072 typedef struct _CEnvelopedDecodeMsg
2074 CRYPT_ENVELOPED_DATA *data;
2075 HCRYPTPROV crypt_prov;
2076 CRYPT_DATA_BLOB content;
2077 BOOL decrypted;
2078 } CEnvelopedDecodeMsg;
2080 typedef struct _CDecodeMsg
2082 CryptMsgBase base;
2083 DWORD type;
2084 HCRYPTPROV crypt_prov;
2085 union {
2086 HCRYPTHASH hash;
2087 CSignedMsgData signed_data;
2088 CEnvelopedDecodeMsg enveloped_data;
2089 } u;
2090 CRYPT_DATA_BLOB msg_data;
2091 CRYPT_DATA_BLOB detached_data;
2092 CONTEXT_PROPERTY_LIST *properties;
2093 } CDecodeMsg;
2095 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg)
2097 CDecodeMsg *msg = hCryptMsg;
2099 if (msg->crypt_prov && msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
2100 CryptReleaseContext(msg->crypt_prov, 0);
2101 switch (msg->type)
2103 case CMSG_HASHED:
2104 if (msg->u.hash)
2105 CryptDestroyHash(msg->u.hash);
2106 break;
2107 case CMSG_ENVELOPED:
2108 if (msg->u.enveloped_data.crypt_prov)
2109 CryptReleaseContext(msg->u.enveloped_data.crypt_prov, 0);
2110 LocalFree(msg->u.enveloped_data.data);
2111 CryptMemFree(msg->u.enveloped_data.content.pbData);
2112 break;
2113 case CMSG_SIGNED:
2114 if (msg->u.signed_data.info)
2116 LocalFree(msg->u.signed_data.info);
2117 CSignedMsgData_CloseHandles(&msg->u.signed_data);
2119 break;
2121 CryptMemFree(msg->msg_data.pbData);
2122 CryptMemFree(msg->detached_data.pbData);
2123 ContextPropertyList_Free(msg->properties);
2126 static BOOL CDecodeMsg_CopyData(CRYPT_DATA_BLOB *blob, const BYTE *pbData,
2127 DWORD cbData)
2129 BOOL ret = TRUE;
2131 if (cbData)
2133 if (blob->cbData)
2134 blob->pbData = CryptMemRealloc(blob->pbData,
2135 blob->cbData + cbData);
2136 else
2137 blob->pbData = CryptMemAlloc(cbData);
2138 if (blob->pbData)
2140 memcpy(blob->pbData + blob->cbData, pbData, cbData);
2141 blob->cbData += cbData;
2143 else
2144 ret = FALSE;
2146 return ret;
2149 static BOOL CDecodeMsg_DecodeDataContent(CDecodeMsg *msg, const CRYPT_DER_BLOB *blob)
2151 BOOL ret;
2152 CRYPT_DATA_BLOB *data;
2153 DWORD size;
2155 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
2156 blob->pbData, blob->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &data, &size);
2157 if (ret)
2159 ret = ContextPropertyList_SetProperty(msg->properties,
2160 CMSG_CONTENT_PARAM, data->pbData, data->cbData);
2161 LocalFree(data);
2163 return ret;
2166 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg *msg, DWORD param,
2167 const CRYPT_ALGORITHM_IDENTIFIER *id)
2169 static const BYTE nullParams[] = { ASN_NULL, 0 };
2170 CRYPT_ALGORITHM_IDENTIFIER *copy;
2171 DWORD len = sizeof(CRYPT_ALGORITHM_IDENTIFIER);
2173 /* Linearize algorithm id */
2174 len += strlen(id->pszObjId) + 1;
2175 len += id->Parameters.cbData;
2176 copy = CryptMemAlloc(len);
2177 if (copy)
2179 copy->pszObjId =
2180 (LPSTR)((BYTE *)copy + sizeof(CRYPT_ALGORITHM_IDENTIFIER));
2181 strcpy(copy->pszObjId, id->pszObjId);
2182 copy->Parameters.pbData = (BYTE *)copy->pszObjId + strlen(id->pszObjId)
2183 + 1;
2184 /* Trick: omit NULL parameters */
2185 if (id->Parameters.cbData == sizeof(nullParams) &&
2186 !memcmp(id->Parameters.pbData, nullParams, sizeof(nullParams)))
2188 copy->Parameters.cbData = 0;
2189 len -= sizeof(nullParams);
2191 else
2192 copy->Parameters.cbData = id->Parameters.cbData;
2193 if (copy->Parameters.cbData)
2194 memcpy(copy->Parameters.pbData, id->Parameters.pbData,
2195 id->Parameters.cbData);
2196 ContextPropertyList_SetProperty(msg->properties, param, (BYTE *)copy,
2197 len);
2198 CryptMemFree(copy);
2202 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER *id)
2204 id->pszObjId = (LPSTR)((BYTE *)id + sizeof(CRYPT_ALGORITHM_IDENTIFIER));
2205 id->Parameters.pbData = (BYTE *)id->pszObjId + strlen(id->pszObjId) + 1;
2208 static BOOL CDecodeMsg_DecodeHashedContent(CDecodeMsg *msg,
2209 const CRYPT_DER_BLOB *blob)
2211 BOOL ret;
2212 CRYPT_DIGESTED_DATA *digestedData;
2213 DWORD size;
2215 ret = CRYPT_AsnDecodePKCSDigestedData(blob->pbData, blob->cbData,
2216 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_DIGESTED_DATA *)&digestedData,
2217 &size);
2218 if (ret)
2220 ContextPropertyList_SetProperty(msg->properties, CMSG_VERSION_PARAM,
2221 (const BYTE *)&digestedData->version, sizeof(digestedData->version));
2222 CDecodeMsg_SaveAlgorithmID(msg, CMSG_HASH_ALGORITHM_PARAM,
2223 &digestedData->DigestAlgorithm);
2224 ContextPropertyList_SetProperty(msg->properties,
2225 CMSG_INNER_CONTENT_TYPE_PARAM,
2226 (const BYTE *)digestedData->ContentInfo.pszObjId,
2227 digestedData->ContentInfo.pszObjId ?
2228 strlen(digestedData->ContentInfo.pszObjId) + 1 : 0);
2229 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG))
2231 if (digestedData->ContentInfo.Content.cbData)
2232 CDecodeMsg_DecodeDataContent(msg,
2233 &digestedData->ContentInfo.Content);
2234 else
2235 ContextPropertyList_SetProperty(msg->properties,
2236 CMSG_CONTENT_PARAM, NULL, 0);
2238 ContextPropertyList_SetProperty(msg->properties, CMSG_HASH_DATA_PARAM,
2239 digestedData->hash.pbData, digestedData->hash.cbData);
2240 LocalFree(digestedData);
2242 return ret;
2245 static BOOL CDecodeMsg_DecodeEnvelopedContent(CDecodeMsg *msg,
2246 const CRYPT_DER_BLOB *blob)
2248 BOOL ret;
2249 CRYPT_ENVELOPED_DATA *envelopedData;
2250 DWORD size;
2252 ret = CRYPT_AsnDecodePKCSEnvelopedData(blob->pbData, blob->cbData,
2253 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_ENVELOPED_DATA *)&envelopedData,
2254 &size);
2255 if (ret)
2256 msg->u.enveloped_data.data = envelopedData;
2257 return ret;
2260 static BOOL CDecodeMsg_DecodeSignedContent(CDecodeMsg *msg,
2261 const CRYPT_DER_BLOB *blob)
2263 BOOL ret;
2264 CRYPT_SIGNED_INFO *signedInfo;
2265 DWORD size;
2267 ret = CRYPT_AsnDecodeCMSSignedInfo(blob->pbData, blob->cbData,
2268 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_SIGNED_INFO *)&signedInfo,
2269 &size);
2270 if (ret)
2271 msg->u.signed_data.info = signedInfo;
2272 return ret;
2275 /* Decodes the content in blob as the type given, and updates the value
2276 * (type, parameters, etc.) of msg based on what blob contains.
2277 * It doesn't just use msg's type, to allow a recursive call from an implicitly
2278 * typed message once the outer content info has been decoded.
2280 static BOOL CDecodeMsg_DecodeContent(CDecodeMsg *msg, const CRYPT_DER_BLOB *blob,
2281 DWORD type)
2283 BOOL ret;
2285 switch (type)
2287 case CMSG_DATA:
2288 if ((ret = CDecodeMsg_DecodeDataContent(msg, blob)))
2289 msg->type = CMSG_DATA;
2290 break;
2291 case CMSG_HASHED:
2292 if ((ret = CDecodeMsg_DecodeHashedContent(msg, blob)))
2293 msg->type = CMSG_HASHED;
2294 break;
2295 case CMSG_ENVELOPED:
2296 if ((ret = CDecodeMsg_DecodeEnvelopedContent(msg, blob)))
2297 msg->type = CMSG_ENVELOPED;
2298 break;
2299 case CMSG_SIGNED:
2300 if ((ret = CDecodeMsg_DecodeSignedContent(msg, blob)))
2301 msg->type = CMSG_SIGNED;
2302 break;
2303 default:
2305 CRYPT_CONTENT_INFO *info;
2306 DWORD size;
2308 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, PKCS_CONTENT_INFO,
2309 msg->msg_data.pbData, msg->msg_data.cbData, CRYPT_DECODE_ALLOC_FLAG,
2310 NULL, &info, &size);
2311 if (ret)
2313 if (!strcmp(info->pszObjId, szOID_RSA_data))
2314 ret = CDecodeMsg_DecodeContent(msg, &info->Content, CMSG_DATA);
2315 else if (!strcmp(info->pszObjId, szOID_RSA_digestedData))
2316 ret = CDecodeMsg_DecodeContent(msg, &info->Content,
2317 CMSG_HASHED);
2318 else if (!strcmp(info->pszObjId, szOID_RSA_envelopedData))
2319 ret = CDecodeMsg_DecodeContent(msg, &info->Content,
2320 CMSG_ENVELOPED);
2321 else if (!strcmp(info->pszObjId, szOID_RSA_signedData))
2322 ret = CDecodeMsg_DecodeContent(msg, &info->Content,
2323 CMSG_SIGNED);
2324 else
2326 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2327 ret = FALSE;
2329 LocalFree(info);
2333 return ret;
2336 static BOOL CDecodeMsg_FinalizeHashedContent(CDecodeMsg *msg,
2337 CRYPT_DER_BLOB *blob)
2339 CRYPT_ALGORITHM_IDENTIFIER *hashAlgoID = NULL;
2340 DWORD size = 0;
2341 ALG_ID algID = 0;
2342 BOOL ret;
2344 CryptMsgGetParam(msg, CMSG_HASH_ALGORITHM_PARAM, 0, NULL, &size);
2345 hashAlgoID = CryptMemAlloc(size);
2346 ret = CryptMsgGetParam(msg, CMSG_HASH_ALGORITHM_PARAM, 0, hashAlgoID,
2347 &size);
2348 if (ret)
2349 algID = CertOIDToAlgId(hashAlgoID->pszObjId);
2351 if (!msg->crypt_prov)
2353 msg->crypt_prov = I_CryptGetDefaultCryptProv(algID);
2354 if (msg->crypt_prov)
2355 msg->base.open_flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
2358 ret = CryptCreateHash(msg->crypt_prov, algID, 0, 0, &msg->u.hash);
2359 if (ret)
2361 CRYPT_DATA_BLOB content;
2363 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
2365 /* Unlike for non-detached messages, the data were never stored as
2366 * the content param, but were saved in msg->detached_data instead.
2368 content.pbData = msg->detached_data.pbData;
2369 content.cbData = msg->detached_data.cbData;
2371 else
2372 ret = ContextPropertyList_FindProperty(msg->properties,
2373 CMSG_CONTENT_PARAM, &content);
2374 if (ret)
2375 ret = CryptHashData(msg->u.hash, content.pbData, content.cbData, 0);
2377 CryptMemFree(hashAlgoID);
2378 return ret;
2381 static BOOL CDecodeMsg_FinalizeEnvelopedContent(CDecodeMsg *msg,
2382 CRYPT_DER_BLOB *blob)
2384 CRYPT_DATA_BLOB *content;
2386 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
2387 content = &msg->detached_data;
2388 else
2389 content =
2390 &msg->u.enveloped_data.data->encryptedContentInfo.encryptedContent;
2392 return CRYPT_ConstructBlob(&msg->u.enveloped_data.content, content);
2395 static BOOL CDecodeMsg_FinalizeSignedContent(CDecodeMsg *msg,
2396 CRYPT_DER_BLOB *blob)
2398 BOOL ret;
2399 DWORD i, size;
2401 ret = CSignedMsgData_AllocateHandles(&msg->u.signed_data);
2402 for (i = 0; ret && i < msg->u.signed_data.info->cSignerInfo; i++)
2403 ret = CSignedMsgData_ConstructSignerHandles(&msg->u.signed_data, i,
2404 &msg->crypt_prov, &msg->base.open_flags);
2405 if (ret)
2407 CRYPT_DATA_BLOB *content;
2409 /* Now that we have all the content, update the hash handles with
2410 * it. If the message is a detached message, the content is stored
2411 * in msg->detached_data rather than in the signed message's
2412 * content.
2414 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
2415 content = &msg->detached_data;
2416 else
2417 content = &msg->u.signed_data.info->content.Content;
2418 if (content->cbData)
2420 /* If the message is not detached, have to decode the message's
2421 * content if the type is szOID_RSA_data.
2423 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG) &&
2424 !strcmp(msg->u.signed_data.info->content.pszObjId,
2425 szOID_RSA_data))
2427 CRYPT_DATA_BLOB *rsa_blob;
2429 ret = CryptDecodeObjectEx(X509_ASN_ENCODING,
2430 X509_OCTET_STRING, content->pbData, content->cbData,
2431 CRYPT_DECODE_ALLOC_FLAG, NULL, &rsa_blob, &size);
2432 if (ret)
2434 ret = CSignedMsgData_Update(&msg->u.signed_data,
2435 rsa_blob->pbData, rsa_blob->cbData, TRUE, Verify);
2436 LocalFree(rsa_blob);
2439 else
2440 ret = CSignedMsgData_Update(&msg->u.signed_data,
2441 content->pbData, content->cbData, TRUE, Verify);
2444 return ret;
2447 static BOOL CDecodeMsg_FinalizeContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob)
2449 BOOL ret = FALSE;
2451 switch (msg->type)
2453 case CMSG_HASHED:
2454 ret = CDecodeMsg_FinalizeHashedContent(msg, blob);
2455 break;
2456 case CMSG_ENVELOPED:
2457 ret = CDecodeMsg_FinalizeEnvelopedContent(msg, blob);
2458 break;
2459 case CMSG_SIGNED:
2460 ret = CDecodeMsg_FinalizeSignedContent(msg, blob);
2461 break;
2462 default:
2463 ret = TRUE;
2465 return ret;
2468 static BOOL CDecodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
2469 DWORD cbData, BOOL fFinal)
2471 CDecodeMsg *msg = hCryptMsg;
2472 BOOL ret = FALSE;
2474 TRACE("(%p, %p, %ld, %d)\n", hCryptMsg, pbData, cbData, fFinal);
2476 if (msg->base.state == MsgStateFinalized)
2477 SetLastError(CRYPT_E_MSG_ERROR);
2478 else if (msg->base.streamed)
2480 FIXME("(%p, %p, %ld, %d): streamed update stub\n", hCryptMsg, pbData,
2481 cbData, fFinal);
2482 switch (msg->base.state)
2484 case MsgStateInit:
2485 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData);
2486 if (fFinal)
2488 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
2489 msg->base.state = MsgStateDataFinalized;
2490 else
2491 msg->base.state = MsgStateFinalized;
2493 else
2494 msg->base.state = MsgStateUpdated;
2495 break;
2496 case MsgStateUpdated:
2497 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData);
2498 if (fFinal)
2500 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
2501 msg->base.state = MsgStateDataFinalized;
2502 else
2503 msg->base.state = MsgStateFinalized;
2505 break;
2506 case MsgStateDataFinalized:
2507 ret = CDecodeMsg_CopyData(&msg->detached_data, pbData, cbData);
2508 if (fFinal)
2509 msg->base.state = MsgStateFinalized;
2510 break;
2511 default:
2512 SetLastError(CRYPT_E_MSG_ERROR);
2513 break;
2516 else
2518 if (!fFinal)
2519 SetLastError(CRYPT_E_MSG_ERROR);
2520 else
2522 switch (msg->base.state)
2524 case MsgStateInit:
2525 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData);
2526 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
2527 msg->base.state = MsgStateDataFinalized;
2528 else
2529 msg->base.state = MsgStateFinalized;
2530 break;
2531 case MsgStateDataFinalized:
2532 ret = CDecodeMsg_CopyData(&msg->detached_data, pbData, cbData);
2533 msg->base.state = MsgStateFinalized;
2534 break;
2535 default:
2536 SetLastError(CRYPT_E_MSG_ERROR);
2540 if (ret && fFinal &&
2541 ((msg->base.open_flags & CMSG_DETACHED_FLAG && msg->base.state ==
2542 MsgStateDataFinalized) ||
2543 (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && msg->base.state ==
2544 MsgStateFinalized)))
2545 ret = CDecodeMsg_DecodeContent(msg, &msg->msg_data, msg->type);
2546 if (ret && msg->base.state == MsgStateFinalized)
2547 ret = CDecodeMsg_FinalizeContent(msg, &msg->msg_data);
2548 return ret;
2551 static BOOL CDecodeHashMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType,
2552 DWORD dwIndex, void *pvData, DWORD *pcbData)
2554 BOOL ret = FALSE;
2556 switch (dwParamType)
2558 case CMSG_TYPE_PARAM:
2559 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type));
2560 break;
2561 case CMSG_HASH_ALGORITHM_PARAM:
2563 CRYPT_DATA_BLOB blob;
2565 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType,
2566 &blob);
2567 if (ret)
2569 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, blob.cbData);
2570 if (ret && pvData)
2571 CRYPT_FixUpAlgorithmID(pvData);
2573 else
2574 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2575 break;
2577 case CMSG_COMPUTED_HASH_PARAM:
2578 ret = CryptGetHashParam(msg->u.hash, HP_HASHVAL, pvData, pcbData, 0);
2579 break;
2580 default:
2582 CRYPT_DATA_BLOB blob;
2584 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType,
2585 &blob);
2586 if (ret)
2587 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, blob.cbData);
2588 else
2589 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2592 return ret;
2595 /* nextData is an in/out parameter - on input it's the memory location in
2596 * which a copy of in's data should be made, and on output it's the memory
2597 * location immediately after out's copy of in's data.
2599 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB *out,
2600 const CRYPT_DATA_BLOB *in, LPBYTE *nextData)
2602 out->cbData = in->cbData;
2603 if (in->cbData)
2605 out->pbData = *nextData;
2606 memcpy(out->pbData, in->pbData, in->cbData);
2607 *nextData += in->cbData;
2611 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER *out,
2612 const CRYPT_ALGORITHM_IDENTIFIER *in, LPBYTE *nextData)
2614 if (in->pszObjId)
2616 out->pszObjId = (LPSTR)*nextData;
2617 strcpy(out->pszObjId, in->pszObjId);
2618 *nextData += strlen(out->pszObjId) + 1;
2620 CRYPT_CopyBlob(&out->Parameters, &in->Parameters, nextData);
2623 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out,
2624 const CRYPT_ATTRIBUTES *in, LPBYTE *nextData)
2626 out->cAttr = in->cAttr;
2627 if (in->cAttr)
2629 DWORD i;
2631 *nextData = POINTER_ALIGN_DWORD_PTR(*nextData);
2632 out->rgAttr = (CRYPT_ATTRIBUTE *)*nextData;
2633 *nextData += in->cAttr * sizeof(CRYPT_ATTRIBUTE);
2634 for (i = 0; i < in->cAttr; i++)
2636 if (in->rgAttr[i].pszObjId)
2638 out->rgAttr[i].pszObjId = (LPSTR)*nextData;
2639 strcpy(out->rgAttr[i].pszObjId, in->rgAttr[i].pszObjId);
2640 *nextData += strlen(in->rgAttr[i].pszObjId) + 1;
2642 if (in->rgAttr[i].cValue)
2644 DWORD j;
2646 out->rgAttr[i].cValue = in->rgAttr[i].cValue;
2647 *nextData = POINTER_ALIGN_DWORD_PTR(*nextData);
2648 out->rgAttr[i].rgValue = (PCRYPT_DATA_BLOB)*nextData;
2649 *nextData += in->rgAttr[i].cValue * sizeof(CRYPT_DATA_BLOB);
2650 for (j = 0; j < in->rgAttr[i].cValue; j++)
2651 CRYPT_CopyBlob(&out->rgAttr[i].rgValue[j],
2652 &in->rgAttr[i].rgValue[j], nextData);
2658 static DWORD CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES *attr)
2660 DWORD size = attr->cAttr * sizeof(CRYPT_ATTRIBUTE), i, j;
2662 for (i = 0; i < attr->cAttr; i++)
2664 if (attr->rgAttr[i].pszObjId)
2665 size += strlen(attr->rgAttr[i].pszObjId) + 1;
2666 /* align pointer */
2667 size = ALIGN_DWORD_PTR(size);
2668 size += attr->rgAttr[i].cValue * sizeof(CRYPT_DATA_BLOB);
2669 for (j = 0; j < attr->rgAttr[i].cValue; j++)
2670 size += attr->rgAttr[i].rgValue[j].cbData;
2672 /* align pointer again to be conservative */
2673 size = ALIGN_DWORD_PTR(size);
2674 return size;
2677 static DWORD CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB *keyId)
2679 static char oid_key_rdn[] = szOID_KEYID_RDN;
2680 DWORD size = 0;
2681 CERT_RDN_ATTR attr;
2682 CERT_RDN rdn = { 1, &attr };
2683 CERT_NAME_INFO name = { 1, &rdn };
2685 attr.pszObjId = oid_key_rdn;
2686 attr.dwValueType = CERT_RDN_OCTET_STRING;
2687 attr.Value.cbData = keyId->cbData;
2688 attr.Value.pbData = keyId->pbData;
2689 if (CryptEncodeObject(X509_ASN_ENCODING, X509_NAME, &name, NULL, &size))
2690 size++; /* Only include size of special zero serial number on success */
2691 return size;
2694 static BOOL CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB *issuer,
2695 CRYPT_INTEGER_BLOB *serialNumber, const CRYPT_DATA_BLOB *keyId, DWORD encodedLen,
2696 LPBYTE *nextData)
2698 static char oid_key_rdn[] = szOID_KEYID_RDN;
2699 CERT_RDN_ATTR attr;
2700 CERT_RDN rdn = { 1, &attr };
2701 CERT_NAME_INFO name = { 1, &rdn };
2702 BOOL ret;
2704 /* Encode special zero serial number */
2705 serialNumber->cbData = 1;
2706 serialNumber->pbData = *nextData;
2707 **nextData = 0;
2708 (*nextData)++;
2709 /* Encode issuer */
2710 issuer->pbData = *nextData;
2711 attr.pszObjId = oid_key_rdn;
2712 attr.dwValueType = CERT_RDN_OCTET_STRING;
2713 attr.Value.cbData = keyId->cbData;
2714 attr.Value.pbData = keyId->pbData;
2715 ret = CryptEncodeObject(X509_ASN_ENCODING, X509_NAME, &name, *nextData,
2716 &encodedLen);
2717 if (ret)
2719 *nextData += encodedLen;
2720 issuer->cbData = encodedLen;
2722 return ret;
2725 static BOOL CRYPT_CopySignerInfo(void *pvData, DWORD *pcbData,
2726 const CMSG_CMS_SIGNER_INFO *in)
2728 DWORD size = sizeof(CMSG_SIGNER_INFO), rdnSize = 0;
2729 BOOL ret;
2731 TRACE("(%p, %ld, %p)\n", pvData, pvData ? *pcbData : 0, in);
2733 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2735 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData;
2736 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData;
2738 else
2740 rdnSize = CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in->SignerId.u.KeyId);
2741 size += rdnSize;
2743 if (in->HashAlgorithm.pszObjId)
2744 size += strlen(in->HashAlgorithm.pszObjId) + 1;
2745 size += in->HashAlgorithm.Parameters.cbData;
2746 if (in->HashEncryptionAlgorithm.pszObjId)
2747 size += strlen(in->HashEncryptionAlgorithm.pszObjId) + 1;
2748 size += in->HashEncryptionAlgorithm.Parameters.cbData;
2749 size += in->EncryptedHash.cbData;
2750 /* align pointer */
2751 size = ALIGN_DWORD_PTR(size);
2752 size += CRYPT_SizeOfAttributes(&in->AuthAttrs);
2753 size += CRYPT_SizeOfAttributes(&in->UnauthAttrs);
2754 if (!pvData)
2756 ret = TRUE;
2758 else if (*pcbData < size)
2760 SetLastError(ERROR_MORE_DATA);
2761 ret = FALSE;
2763 else
2765 LPBYTE nextData = (BYTE *)pvData + sizeof(CMSG_SIGNER_INFO);
2766 CMSG_SIGNER_INFO *out = pvData;
2768 ret = TRUE;
2769 out->dwVersion = in->dwVersion;
2770 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2772 CRYPT_CopyBlob(&out->Issuer,
2773 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData);
2774 CRYPT_CopyBlob(&out->SerialNumber,
2775 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData);
2777 else
2778 ret = CRYPT_CopyKeyIdAsIssuerAndSerial(&out->Issuer, &out->SerialNumber,
2779 &in->SignerId.u.KeyId, rdnSize, &nextData);
2780 if (ret)
2782 CRYPT_CopyAlgorithmId(&out->HashAlgorithm, &in->HashAlgorithm,
2783 &nextData);
2784 CRYPT_CopyAlgorithmId(&out->HashEncryptionAlgorithm,
2785 &in->HashEncryptionAlgorithm, &nextData);
2786 CRYPT_CopyBlob(&out->EncryptedHash, &in->EncryptedHash, &nextData);
2787 nextData = POINTER_ALIGN_DWORD_PTR(nextData);
2788 CRYPT_CopyAttributes(&out->AuthAttrs, &in->AuthAttrs, &nextData);
2789 CRYPT_CopyAttributes(&out->UnauthAttrs, &in->UnauthAttrs, &nextData);
2792 *pcbData = size;
2793 TRACE("returning %d\n", ret);
2794 return ret;
2797 static BOOL CRYPT_CopyCMSSignerInfo(void *pvData, DWORD *pcbData,
2798 const CMSG_CMS_SIGNER_INFO *in)
2800 DWORD size = sizeof(CMSG_CMS_SIGNER_INFO);
2801 BOOL ret;
2803 TRACE("(%p, %ld, %p)\n", pvData, pvData ? *pcbData : 0, in);
2805 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2807 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData;
2808 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData;
2810 else
2811 size += in->SignerId.u.KeyId.cbData;
2812 if (in->HashAlgorithm.pszObjId)
2813 size += strlen(in->HashAlgorithm.pszObjId) + 1;
2814 size += in->HashAlgorithm.Parameters.cbData;
2815 if (in->HashEncryptionAlgorithm.pszObjId)
2816 size += strlen(in->HashEncryptionAlgorithm.pszObjId) + 1;
2817 size += in->HashEncryptionAlgorithm.Parameters.cbData;
2818 size += in->EncryptedHash.cbData;
2819 /* align pointer */
2820 size = ALIGN_DWORD_PTR(size);
2821 size += CRYPT_SizeOfAttributes(&in->AuthAttrs);
2822 size += CRYPT_SizeOfAttributes(&in->UnauthAttrs);
2823 if (!pvData)
2825 *pcbData = size;
2826 ret = TRUE;
2828 else if (*pcbData < size)
2830 *pcbData = size;
2831 SetLastError(ERROR_MORE_DATA);
2832 ret = FALSE;
2834 else
2836 LPBYTE nextData = (BYTE *)pvData + sizeof(CMSG_CMS_SIGNER_INFO);
2837 CMSG_CMS_SIGNER_INFO *out = pvData;
2839 out->dwVersion = in->dwVersion;
2840 out->SignerId.dwIdChoice = in->SignerId.dwIdChoice;
2841 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2843 CRYPT_CopyBlob(&out->SignerId.u.IssuerSerialNumber.Issuer,
2844 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData);
2845 CRYPT_CopyBlob(&out->SignerId.u.IssuerSerialNumber.SerialNumber,
2846 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData);
2848 else
2849 CRYPT_CopyBlob(&out->SignerId.u.KeyId, &in->SignerId.u.KeyId, &nextData);
2850 CRYPT_CopyAlgorithmId(&out->HashAlgorithm, &in->HashAlgorithm,
2851 &nextData);
2852 CRYPT_CopyAlgorithmId(&out->HashEncryptionAlgorithm,
2853 &in->HashEncryptionAlgorithm, &nextData);
2854 CRYPT_CopyBlob(&out->EncryptedHash, &in->EncryptedHash, &nextData);
2855 nextData = POINTER_ALIGN_DWORD_PTR(nextData);
2856 CRYPT_CopyAttributes(&out->AuthAttrs, &in->AuthAttrs, &nextData);
2857 CRYPT_CopyAttributes(&out->UnauthAttrs, &in->UnauthAttrs, &nextData);
2858 ret = TRUE;
2860 TRACE("returning %d\n", ret);
2861 return ret;
2864 static BOOL CRYPT_CopySignerCertInfo(void *pvData, DWORD *pcbData,
2865 const CMSG_CMS_SIGNER_INFO *in)
2867 DWORD size = sizeof(CERT_INFO), rdnSize = 0;
2868 BOOL ret;
2870 TRACE("(%p, %ld, %p)\n", pvData, pvData ? *pcbData : 0, in);
2872 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2874 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData;
2875 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData;
2877 else
2879 rdnSize = CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in->SignerId.u.KeyId);
2880 size += rdnSize;
2882 if (!pvData)
2884 *pcbData = size;
2885 ret = TRUE;
2887 else if (*pcbData < size)
2889 *pcbData = size;
2890 SetLastError(ERROR_MORE_DATA);
2891 ret = FALSE;
2893 else
2895 LPBYTE nextData = (BYTE *)pvData + sizeof(CERT_INFO);
2896 CERT_INFO *out = pvData;
2898 memset(out, 0, sizeof(CERT_INFO));
2899 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2901 CRYPT_CopyBlob(&out->Issuer,
2902 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData);
2903 CRYPT_CopyBlob(&out->SerialNumber,
2904 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData);
2905 ret = TRUE;
2907 else
2908 ret = CRYPT_CopyKeyIdAsIssuerAndSerial(&out->Issuer, &out->SerialNumber,
2909 &in->SignerId.u.KeyId, rdnSize, &nextData);
2911 TRACE("returning %d\n", ret);
2912 return ret;
2915 static BOOL CRYPT_CopyRecipientInfo(void *pvData, DWORD *pcbData,
2916 const CERT_ISSUER_SERIAL_NUMBER *in)
2918 DWORD size = sizeof(CERT_INFO);
2919 BOOL ret;
2921 TRACE("(%p, %ld, %p)\n", pvData, pvData ? *pcbData : 0, in);
2923 size += in->SerialNumber.cbData;
2924 size += in->Issuer.cbData;
2925 if (!pvData)
2927 *pcbData = size;
2928 ret = TRUE;
2930 else if (*pcbData < size)
2932 *pcbData = size;
2933 SetLastError(ERROR_MORE_DATA);
2934 ret = FALSE;
2936 else
2938 LPBYTE nextData = (BYTE *)pvData + sizeof(CERT_INFO);
2939 CERT_INFO *out = pvData;
2941 CRYPT_CopyBlob(&out->SerialNumber, &in->SerialNumber, &nextData);
2942 CRYPT_CopyBlob(&out->Issuer, &in->Issuer, &nextData);
2943 ret = TRUE;
2945 TRACE("returning %d\n", ret);
2946 return ret;
2949 static BOOL CDecodeEnvelopedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType,
2950 DWORD dwIndex, void *pvData, DWORD *pcbData)
2952 BOOL ret = FALSE;
2954 switch (dwParamType)
2956 case CMSG_TYPE_PARAM:
2957 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type));
2958 break;
2959 case CMSG_CONTENT_PARAM:
2960 if (msg->u.enveloped_data.data)
2961 ret = CRYPT_CopyParam(pvData, pcbData,
2962 msg->u.enveloped_data.content.pbData,
2963 msg->u.enveloped_data.content.cbData);
2964 else
2965 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2966 break;
2967 case CMSG_RECIPIENT_COUNT_PARAM:
2968 if (msg->u.enveloped_data.data)
2969 ret = CRYPT_CopyParam(pvData, pcbData,
2970 &msg->u.enveloped_data.data->cRecipientInfo, sizeof(DWORD));
2971 else
2972 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2973 break;
2974 case CMSG_RECIPIENT_INFO_PARAM:
2975 if (msg->u.enveloped_data.data)
2977 if (dwIndex < msg->u.enveloped_data.data->cRecipientInfo)
2979 PCMSG_KEY_TRANS_RECIPIENT_INFO recipientInfo =
2980 &msg->u.enveloped_data.data->rgRecipientInfo[dwIndex];
2982 ret = CRYPT_CopyRecipientInfo(pvData, pcbData,
2983 &recipientInfo->RecipientId.u.IssuerSerialNumber);
2985 else
2986 SetLastError(CRYPT_E_INVALID_INDEX);
2988 else
2989 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2990 break;
2991 default:
2992 FIXME("unimplemented for %ld\n", dwParamType);
2993 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2995 return ret;
2998 static BOOL CRYPT_CopyAttr(void *pvData, DWORD *pcbData, const CRYPT_ATTRIBUTES *attr)
3000 DWORD size;
3001 BOOL ret;
3003 TRACE("(%p, %ld, %p)\n", pvData, pvData ? *pcbData : 0, attr);
3005 size = CRYPT_SizeOfAttributes(attr);
3006 if (!pvData)
3008 *pcbData = size;
3009 ret = TRUE;
3011 else if (*pcbData < size)
3013 *pcbData = size;
3014 SetLastError(ERROR_MORE_DATA);
3015 ret = FALSE;
3017 else
3018 ret = CRYPT_ConstructAttributes(pvData, attr);
3020 TRACE("returning %d\n", ret);
3021 return ret;
3024 static BOOL CDecodeSignedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType,
3025 DWORD dwIndex, void *pvData, DWORD *pcbData)
3027 BOOL ret = FALSE;
3029 switch (dwParamType)
3031 case CMSG_TYPE_PARAM:
3032 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type));
3033 break;
3034 case CMSG_CONTENT_PARAM:
3035 if (msg->u.signed_data.info)
3037 if (!strcmp(msg->u.signed_data.info->content.pszObjId,
3038 szOID_RSA_data))
3040 CRYPT_DATA_BLOB *blob;
3041 DWORD size;
3043 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
3044 msg->u.signed_data.info->content.Content.pbData,
3045 msg->u.signed_data.info->content.Content.cbData,
3046 CRYPT_DECODE_ALLOC_FLAG, NULL, &blob, &size);
3047 if (ret)
3049 ret = CRYPT_CopyParam(pvData, pcbData, blob->pbData,
3050 blob->cbData);
3051 LocalFree(blob);
3054 else
3055 ret = CRYPT_CopyParam(pvData, pcbData,
3056 msg->u.signed_data.info->content.Content.pbData,
3057 msg->u.signed_data.info->content.Content.cbData);
3059 else
3060 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3061 break;
3062 case CMSG_INNER_CONTENT_TYPE_PARAM:
3063 if (msg->u.signed_data.info)
3064 ret = CRYPT_CopyParam(pvData, pcbData,
3065 msg->u.signed_data.info->content.pszObjId,
3066 strlen(msg->u.signed_data.info->content.pszObjId) + 1);
3067 else
3068 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3069 break;
3070 case CMSG_SIGNER_COUNT_PARAM:
3071 if (msg->u.signed_data.info)
3072 ret = CRYPT_CopyParam(pvData, pcbData,
3073 &msg->u.signed_data.info->cSignerInfo, sizeof(DWORD));
3074 else
3075 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3076 break;
3077 case CMSG_SIGNER_INFO_PARAM:
3078 if (msg->u.signed_data.info)
3080 if (dwIndex >= msg->u.signed_data.info->cSignerInfo)
3081 SetLastError(CRYPT_E_INVALID_INDEX);
3082 else
3083 ret = CRYPT_CopySignerInfo(pvData, pcbData,
3084 &msg->u.signed_data.info->rgSignerInfo[dwIndex]);
3086 else
3087 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3088 break;
3089 case CMSG_SIGNER_CERT_INFO_PARAM:
3090 if (msg->u.signed_data.info)
3092 if (dwIndex >= msg->u.signed_data.info->cSignerInfo)
3093 SetLastError(CRYPT_E_INVALID_INDEX);
3094 else
3095 ret = CRYPT_CopySignerCertInfo(pvData, pcbData,
3096 &msg->u.signed_data.info->rgSignerInfo[dwIndex]);
3098 else
3099 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3100 break;
3101 case CMSG_CERT_COUNT_PARAM:
3102 if (msg->u.signed_data.info)
3103 ret = CRYPT_CopyParam(pvData, pcbData,
3104 &msg->u.signed_data.info->cCertEncoded, sizeof(DWORD));
3105 else
3106 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3107 break;
3108 case CMSG_CERT_PARAM:
3109 if (msg->u.signed_data.info)
3111 if (dwIndex >= msg->u.signed_data.info->cCertEncoded)
3112 SetLastError(CRYPT_E_INVALID_INDEX);
3113 else
3114 ret = CRYPT_CopyParam(pvData, pcbData,
3115 msg->u.signed_data.info->rgCertEncoded[dwIndex].pbData,
3116 msg->u.signed_data.info->rgCertEncoded[dwIndex].cbData);
3118 else
3119 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3120 break;
3121 case CMSG_CRL_COUNT_PARAM:
3122 if (msg->u.signed_data.info)
3123 ret = CRYPT_CopyParam(pvData, pcbData,
3124 &msg->u.signed_data.info->cCrlEncoded, sizeof(DWORD));
3125 else
3126 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3127 break;
3128 case CMSG_CRL_PARAM:
3129 if (msg->u.signed_data.info)
3131 if (dwIndex >= msg->u.signed_data.info->cCrlEncoded)
3132 SetLastError(CRYPT_E_INVALID_INDEX);
3133 else
3134 ret = CRYPT_CopyParam(pvData, pcbData,
3135 msg->u.signed_data.info->rgCrlEncoded[dwIndex].pbData,
3136 msg->u.signed_data.info->rgCrlEncoded[dwIndex].cbData);
3138 else
3139 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3140 break;
3141 case CMSG_COMPUTED_HASH_PARAM:
3142 if (msg->u.signed_data.info)
3144 if (dwIndex >= msg->u.signed_data.cSignerHandle)
3145 SetLastError(CRYPT_E_INVALID_INDEX);
3146 else
3147 ret = CryptGetHashParam(
3148 msg->u.signed_data.signerHandles[dwIndex].contentHash,
3149 HP_HASHVAL, pvData, pcbData, 0);
3151 else
3152 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3153 break;
3154 case CMSG_ENCODED_MESSAGE:
3155 if (msg->msg_data.pbData)
3156 ret = CRYPT_CopyParam(pvData, pcbData, msg->msg_data.pbData, msg->msg_data.cbData);
3157 else
3158 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3159 break;
3160 case CMSG_ENCODED_SIGNER:
3161 if (msg->u.signed_data.info)
3163 if (dwIndex >= msg->u.signed_data.info->cSignerInfo)
3164 SetLastError(CRYPT_E_INVALID_INDEX);
3165 else
3166 ret = CryptEncodeObjectEx(
3167 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CMS_SIGNER_INFO,
3168 &msg->u.signed_data.info->rgSignerInfo[dwIndex], 0, NULL,
3169 pvData, pcbData);
3171 else
3172 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3173 break;
3174 case CMSG_ATTR_CERT_COUNT_PARAM:
3175 if (msg->u.signed_data.info)
3177 DWORD attrCertCount = 0;
3179 ret = CRYPT_CopyParam(pvData, pcbData,
3180 &attrCertCount, sizeof(DWORD));
3182 else
3183 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3184 break;
3185 case CMSG_ATTR_CERT_PARAM:
3186 if (msg->u.signed_data.info)
3187 SetLastError(CRYPT_E_INVALID_INDEX);
3188 else
3189 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3190 break;
3191 case CMSG_CMS_SIGNER_INFO_PARAM:
3192 if (msg->u.signed_data.info)
3194 if (dwIndex >= msg->u.signed_data.info->cSignerInfo)
3195 SetLastError(CRYPT_E_INVALID_INDEX);
3196 else
3197 ret = CRYPT_CopyCMSSignerInfo(pvData, pcbData,
3198 &msg->u.signed_data.info->rgSignerInfo[dwIndex]);
3200 else
3201 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3202 break;
3203 case CMSG_SIGNER_AUTH_ATTR_PARAM:
3204 if (msg->u.signed_data.info)
3206 if (dwIndex >= msg->u.signed_data.info->cSignerInfo)
3207 SetLastError(CRYPT_E_INVALID_INDEX);
3208 else
3209 ret = CRYPT_CopyAttr(pvData, pcbData,
3210 &msg->u.signed_data.info->rgSignerInfo[dwIndex].AuthAttrs);
3212 else
3213 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3214 break;
3215 case CMSG_SIGNER_UNAUTH_ATTR_PARAM:
3216 if (msg->u.signed_data.info)
3218 if (dwIndex >= msg->u.signed_data.info->cSignerInfo)
3219 SetLastError(CRYPT_E_INVALID_INDEX);
3220 else
3221 ret = CRYPT_CopyAttr(pvData, pcbData,
3222 &msg->u.signed_data.info->rgSignerInfo[dwIndex].UnauthAttrs);
3224 else
3225 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3226 break;
3227 default:
3228 FIXME("unimplemented for %ld\n", dwParamType);
3229 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3231 return ret;
3234 static BOOL CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
3235 DWORD dwIndex, void *pvData, DWORD *pcbData)
3237 CDecodeMsg *msg = hCryptMsg;
3238 BOOL ret = FALSE;
3240 switch (msg->type)
3242 case CMSG_HASHED:
3243 ret = CDecodeHashMsg_GetParam(msg, dwParamType, dwIndex, pvData,
3244 pcbData);
3245 break;
3246 case CMSG_ENVELOPED:
3247 ret = CDecodeEnvelopedMsg_GetParam(msg, dwParamType, dwIndex, pvData,
3248 pcbData);
3249 break;
3250 case CMSG_SIGNED:
3251 ret = CDecodeSignedMsg_GetParam(msg, dwParamType, dwIndex, pvData,
3252 pcbData);
3253 break;
3254 default:
3255 switch (dwParamType)
3257 case CMSG_TYPE_PARAM:
3258 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type,
3259 sizeof(msg->type));
3260 break;
3261 default:
3263 CRYPT_DATA_BLOB blob;
3265 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType,
3266 &blob);
3267 if (ret)
3268 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData,
3269 blob.cbData);
3270 else
3271 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3275 return ret;
3278 static BOOL CDecodeHashMsg_VerifyHash(CDecodeMsg *msg)
3280 BOOL ret;
3281 CRYPT_DATA_BLOB hashBlob;
3283 ret = ContextPropertyList_FindProperty(msg->properties,
3284 CMSG_HASH_DATA_PARAM, &hashBlob);
3285 if (ret)
3287 DWORD computedHashSize = 0;
3289 ret = CDecodeHashMsg_GetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL,
3290 &computedHashSize);
3291 if (hashBlob.cbData == computedHashSize)
3293 LPBYTE computedHash = CryptMemAlloc(computedHashSize);
3295 if (computedHash)
3297 ret = CDecodeHashMsg_GetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
3298 computedHash, &computedHashSize);
3299 if (ret)
3301 if (memcmp(hashBlob.pbData, computedHash, hashBlob.cbData))
3303 SetLastError(CRYPT_E_HASH_VALUE);
3304 ret = FALSE;
3307 CryptMemFree(computedHash);
3309 else
3311 SetLastError(ERROR_OUTOFMEMORY);
3312 ret = FALSE;
3315 else
3317 SetLastError(CRYPT_E_HASH_VALUE);
3318 ret = FALSE;
3321 return ret;
3324 static BOOL CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg *msg,
3325 HCRYPTPROV prov, DWORD signerIndex, PCERT_PUBLIC_KEY_INFO keyInfo)
3327 HCRYPTKEY key;
3328 BOOL ret;
3330 if (!prov)
3331 prov = msg->crypt_prov;
3332 ret = CryptImportPublicKeyInfo(prov, X509_ASN_ENCODING, keyInfo, &key);
3333 if (ret)
3335 HCRYPTHASH hash;
3336 CRYPT_HASH_BLOB reversedHash;
3338 if (msg->u.signed_data.info->rgSignerInfo[signerIndex].AuthAttrs.cAttr)
3339 hash = msg->u.signed_data.signerHandles[signerIndex].authAttrHash;
3340 else
3341 hash = msg->u.signed_data.signerHandles[signerIndex].contentHash;
3342 ret = CRYPT_ConstructBlob(&reversedHash,
3343 &msg->u.signed_data.info->rgSignerInfo[signerIndex].EncryptedHash);
3344 if (ret)
3346 CRYPT_ReverseBytes(&reversedHash);
3347 ret = CryptVerifySignatureW(hash, reversedHash.pbData,
3348 reversedHash.cbData, key, NULL, 0);
3349 CryptMemFree(reversedHash.pbData);
3351 CryptDestroyKey(key);
3353 return ret;
3356 static BOOL CDecodeSignedMsg_VerifySignature(CDecodeMsg *msg, PCERT_INFO info)
3358 BOOL ret = FALSE;
3359 DWORD i;
3361 if (!msg->u.signed_data.signerHandles)
3363 SetLastError(NTE_BAD_SIGNATURE);
3364 return FALSE;
3366 for (i = 0; !ret && i < msg->u.signed_data.info->cSignerInfo; i++)
3368 PCMSG_CMS_SIGNER_INFO signerInfo =
3369 &msg->u.signed_data.info->rgSignerInfo[i];
3371 if (signerInfo->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
3373 ret = CertCompareCertificateName(X509_ASN_ENCODING,
3374 &signerInfo->SignerId.u.IssuerSerialNumber.Issuer,
3375 &info->Issuer);
3376 if (ret)
3378 ret = CertCompareIntegerBlob(
3379 &signerInfo->SignerId.u.IssuerSerialNumber.SerialNumber,
3380 &info->SerialNumber);
3381 if (ret)
3382 break;
3385 else
3387 FIXME("signer %ld: unimplemented for key id\n", i);
3390 if (ret)
3391 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, 0, i,
3392 &info->SubjectPublicKeyInfo);
3393 else
3394 SetLastError(CRYPT_E_SIGNER_NOT_FOUND);
3396 return ret;
3399 static BOOL CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg *msg,
3400 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para)
3402 BOOL ret = FALSE;
3404 if (para->cbSize != sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA))
3405 SetLastError(ERROR_INVALID_PARAMETER);
3406 else if (para->dwSignerIndex >= msg->u.signed_data.info->cSignerInfo)
3407 SetLastError(CRYPT_E_SIGNER_NOT_FOUND);
3408 else if (!msg->u.signed_data.signerHandles)
3409 SetLastError(NTE_BAD_SIGNATURE);
3410 else
3412 switch (para->dwSignerType)
3414 case CMSG_VERIFY_SIGNER_PUBKEY:
3415 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg,
3416 para->hCryptProv, para->dwSignerIndex, para->pvSigner);
3417 break;
3418 case CMSG_VERIFY_SIGNER_CERT:
3420 PCCERT_CONTEXT cert = para->pvSigner;
3422 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, para->hCryptProv,
3423 para->dwSignerIndex, &cert->pCertInfo->SubjectPublicKeyInfo);
3424 break;
3426 default:
3427 FIXME("unimplemented for signer type %ld\n", para->dwSignerType);
3428 SetLastError(CRYPT_E_SIGNER_NOT_FOUND);
3431 return ret;
3434 static BOOL WINAPI CRYPT_ImportKeyTrans(
3435 PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
3436 PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara, DWORD dwFlags,
3437 void *pvReserved, HCRYPTKEY *phContentEncryptKey)
3439 BOOL ret;
3440 HCRYPTKEY key;
3442 ret = CryptGetUserKey(pKeyTransDecryptPara->hCryptProv,
3443 pKeyTransDecryptPara->dwKeySpec ? pKeyTransDecryptPara->dwKeySpec :
3444 AT_KEYEXCHANGE, &key);
3445 if (ret)
3447 CMSG_KEY_TRANS_RECIPIENT_INFO *info =
3448 &pKeyTransDecryptPara->pKeyTrans[pKeyTransDecryptPara->dwRecipientIndex];
3449 CRYPT_DATA_BLOB *encryptedKey = &info->EncryptedKey;
3450 DWORD size = encryptedKey->cbData + sizeof(BLOBHEADER) + sizeof(ALG_ID);
3451 BYTE *keyBlob = CryptMemAlloc(size);
3453 if (keyBlob)
3455 DWORD i, k = size - 1;
3456 BLOBHEADER *blobHeader = (BLOBHEADER *)keyBlob;
3457 ALG_ID *algID = (ALG_ID *)(keyBlob + sizeof(BLOBHEADER));
3459 blobHeader->bType = SIMPLEBLOB;
3460 blobHeader->bVersion = CUR_BLOB_VERSION;
3461 blobHeader->reserved = 0;
3462 blobHeader->aiKeyAlg = CertOIDToAlgId(
3463 pContentEncryptionAlgorithm->pszObjId);
3464 *algID = CertOIDToAlgId(info->KeyEncryptionAlgorithm.pszObjId);
3465 for (i = 0; i < encryptedKey->cbData; ++i, --k)
3466 keyBlob[k] = encryptedKey->pbData[i];
3468 ret = CryptImportKey(pKeyTransDecryptPara->hCryptProv, keyBlob,
3469 size, key, 0, phContentEncryptKey);
3470 CryptMemFree(keyBlob);
3472 else
3473 ret = FALSE;
3474 CryptDestroyKey(key);
3476 return ret;
3479 static BOOL CRYPT_ImportEncryptedKey(PCRYPT_ALGORITHM_IDENTIFIER contEncrAlg,
3480 PCMSG_CTRL_DECRYPT_PARA para, PCMSG_KEY_TRANS_RECIPIENT_INFO info,
3481 HCRYPTKEY *key)
3483 static HCRYPTOIDFUNCSET set = NULL;
3484 PFN_CMSG_IMPORT_KEY_TRANS importKeyFunc = NULL;
3485 HCRYPTOIDFUNCADDR hFunc = NULL;
3486 CMSG_CTRL_KEY_TRANS_DECRYPT_PARA decryptPara;
3487 BOOL ret;
3489 memset(&decryptPara, 0, sizeof(decryptPara));
3490 decryptPara.cbSize = sizeof(decryptPara);
3491 decryptPara.hCryptProv = para->hCryptProv;
3492 decryptPara.dwKeySpec = para->dwKeySpec;
3493 decryptPara.pKeyTrans = info;
3494 decryptPara.dwRecipientIndex = para->dwRecipientIndex;
3496 if (!set)
3497 set = CryptInitOIDFunctionSet(CMSG_OID_IMPORT_KEY_TRANS_FUNC, 0);
3498 CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, contEncrAlg->pszObjId, 0,
3499 (void **)&importKeyFunc, &hFunc);
3500 if (!importKeyFunc)
3501 importKeyFunc = CRYPT_ImportKeyTrans;
3502 ret = importKeyFunc(contEncrAlg, &decryptPara, 0, NULL, key);
3503 if (hFunc)
3504 CryptFreeOIDFunctionAddress(hFunc, 0);
3505 return ret;
3508 static BOOL CDecodeEnvelopedMsg_CrtlDecrypt(CDecodeMsg *msg,
3509 PCMSG_CTRL_DECRYPT_PARA para)
3511 BOOL ret = FALSE;
3512 CEnvelopedDecodeMsg *enveloped_data = &msg->u.enveloped_data;
3513 CRYPT_ENVELOPED_DATA *data = enveloped_data->data;
3515 if (para->cbSize != sizeof(CMSG_CTRL_DECRYPT_PARA))
3516 SetLastError(E_INVALIDARG);
3517 else if (!data)
3518 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3519 else if (para->dwRecipientIndex >= data->cRecipientInfo)
3520 SetLastError(CRYPT_E_INVALID_INDEX);
3521 else if (enveloped_data->decrypted)
3522 SetLastError(CRYPT_E_ALREADY_DECRYPTED);
3523 else if (!para->hCryptProv)
3524 SetLastError(ERROR_INVALID_PARAMETER);
3525 else if (enveloped_data->content.cbData)
3527 HCRYPTKEY key;
3529 ret = CRYPT_ImportEncryptedKey(
3530 &data->encryptedContentInfo.contentEncryptionAlgorithm, para,
3531 data->rgRecipientInfo, &key);
3532 if (ret)
3534 ret = CryptDecrypt(key, 0, TRUE, 0, enveloped_data->content.pbData,
3535 &enveloped_data->content.cbData);
3536 CryptDestroyKey(key);
3539 else
3540 ret = TRUE;
3541 if (ret)
3542 enveloped_data->decrypted = TRUE;
3543 return ret;
3546 static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags,
3547 DWORD dwCtrlType, const void *pvCtrlPara)
3549 CDecodeMsg *msg = hCryptMsg;
3550 BOOL ret = FALSE;
3552 switch (dwCtrlType)
3554 case CMSG_CTRL_VERIFY_SIGNATURE:
3555 switch (msg->type)
3557 case CMSG_SIGNED:
3558 ret = CDecodeSignedMsg_VerifySignature(msg, (PCERT_INFO)pvCtrlPara);
3559 break;
3560 default:
3561 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3563 break;
3564 case CMSG_CTRL_DECRYPT:
3565 switch (msg->type)
3567 case CMSG_ENVELOPED:
3568 ret = CDecodeEnvelopedMsg_CrtlDecrypt(msg,
3569 (PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara);
3570 if (ret && (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG))
3571 msg->u.enveloped_data.crypt_prov =
3572 ((PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara)->hCryptProv;
3573 break;
3574 default:
3575 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3577 break;
3578 case CMSG_CTRL_VERIFY_HASH:
3579 switch (msg->type)
3581 case CMSG_HASHED:
3582 ret = CDecodeHashMsg_VerifyHash(msg);
3583 break;
3584 default:
3585 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3587 break;
3588 case CMSG_CTRL_VERIFY_SIGNATURE_EX:
3589 switch (msg->type)
3591 case CMSG_SIGNED:
3592 ret = CDecodeSignedMsg_VerifySignatureEx(msg,
3593 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA)pvCtrlPara);
3594 break;
3595 default:
3596 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
3598 break;
3599 default:
3600 SetLastError(CRYPT_E_CONTROL_TYPE);
3602 return ret;
3605 HCRYPTMSG WINAPI CryptMsgOpenToDecode(DWORD dwMsgEncodingType, DWORD dwFlags,
3606 DWORD dwMsgType, HCRYPTPROV_LEGACY hCryptProv, PCERT_INFO pRecipientInfo,
3607 PCMSG_STREAM_INFO pStreamInfo)
3609 CDecodeMsg *msg;
3611 TRACE("(%08lx, %08lx, %08lx, %08Ix, %p, %p)\n", dwMsgEncodingType,
3612 dwFlags, dwMsgType, hCryptProv, pRecipientInfo, pStreamInfo);
3614 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING)
3616 SetLastError(E_INVALIDARG);
3617 return NULL;
3619 msg = CryptMemAlloc(sizeof(CDecodeMsg));
3620 if (msg)
3622 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo,
3623 CDecodeMsg_Close, CDecodeMsg_GetParam, CDecodeMsg_Update,
3624 CDecodeMsg_Control);
3625 msg->type = dwMsgType;
3626 msg->crypt_prov = hCryptProv;
3627 memset(&msg->u, 0, sizeof(msg->u));
3628 msg->msg_data.cbData = 0;
3629 msg->msg_data.pbData = NULL;
3630 msg->detached_data.cbData = 0;
3631 msg->detached_data.pbData = NULL;
3632 msg->properties = ContextPropertyList_Create();
3634 return msg;
3637 HCRYPTMSG WINAPI CryptMsgDuplicate(HCRYPTMSG hCryptMsg)
3639 TRACE("(%p)\n", hCryptMsg);
3641 if (hCryptMsg)
3643 CryptMsgBase *msg = hCryptMsg;
3645 InterlockedIncrement(&msg->ref);
3647 return hCryptMsg;
3650 BOOL WINAPI CryptMsgClose(HCRYPTMSG hCryptMsg)
3652 TRACE("(%p)\n", hCryptMsg);
3654 if (hCryptMsg)
3656 CryptMsgBase *msg = hCryptMsg;
3658 if (InterlockedDecrement(&msg->ref) == 0)
3660 TRACE("freeing %p\n", msg);
3661 if (msg->close)
3662 msg->close(msg);
3663 CryptMemFree(msg);
3666 return TRUE;
3669 BOOL WINAPI CryptMsgUpdate(HCRYPTMSG hCryptMsg, const BYTE *pbData,
3670 DWORD cbData, BOOL fFinal)
3672 CryptMsgBase *msg = hCryptMsg;
3674 TRACE("(%p, %p, %ld, %d)\n", hCryptMsg, pbData, cbData, fFinal);
3676 return msg->update(hCryptMsg, pbData, cbData, fFinal);
3679 BOOL WINAPI CryptMsgGetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
3680 DWORD dwIndex, void *pvData, DWORD *pcbData)
3682 CryptMsgBase *msg = hCryptMsg;
3684 TRACE("(%p, %ld, %ld, %p, %p)\n", hCryptMsg, dwParamType, dwIndex,
3685 pvData, pcbData);
3686 return msg->get_param(hCryptMsg, dwParamType, dwIndex, pvData, pcbData);
3689 BOOL WINAPI CryptMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags,
3690 DWORD dwCtrlType, const void *pvCtrlPara)
3692 CryptMsgBase *msg = hCryptMsg;
3694 TRACE("(%p, %08lx, %ld, %p)\n", hCryptMsg, dwFlags, dwCtrlType,
3695 pvCtrlPara);
3696 return msg->control(hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara);
3699 static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg,
3700 DWORD dwSignerIndex)
3702 CERT_INFO *certInfo = NULL;
3703 DWORD size;
3705 if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL,
3706 &size))
3708 certInfo = CryptMemAlloc(size);
3709 if (certInfo)
3711 if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM,
3712 dwSignerIndex, certInfo, &size))
3714 CryptMemFree(certInfo);
3715 certInfo = NULL;
3719 return certInfo;
3722 BOOL WINAPI CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg, DWORD cSignerStore,
3723 HCERTSTORE *rghSignerStore, DWORD dwFlags, PCCERT_CONTEXT *ppSigner,
3724 DWORD *pdwSignerIndex)
3726 HCERTSTORE store;
3727 DWORD i, signerIndex = 0;
3728 PCCERT_CONTEXT signerCert = NULL;
3729 BOOL ret = FALSE;
3731 TRACE("(%p, %ld, %p, %08lx, %p, %p)\n", hCryptMsg, cSignerStore,
3732 rghSignerStore, dwFlags, ppSigner, pdwSignerIndex);
3734 /* Clear output parameters */
3735 if (ppSigner)
3736 *ppSigner = NULL;
3737 if (pdwSignerIndex && !(dwFlags & CMSG_USE_SIGNER_INDEX_FLAG))
3738 *pdwSignerIndex = 0;
3740 /* Create store to search for signer certificates */
3741 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
3742 CERT_STORE_CREATE_NEW_FLAG, NULL);
3743 if (!(dwFlags & CMSG_TRUSTED_SIGNER_FLAG))
3745 HCERTSTORE msgStore = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0,
3746 hCryptMsg);
3748 CertAddStoreToCollection(store, msgStore, 0, 0);
3749 CertCloseStore(msgStore, 0);
3751 for (i = 0; i < cSignerStore; i++)
3752 CertAddStoreToCollection(store, rghSignerStore[i], 0, 0);
3754 /* Find signer cert */
3755 if (dwFlags & CMSG_USE_SIGNER_INDEX_FLAG)
3757 CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg,
3758 *pdwSignerIndex);
3760 if (signer)
3762 signerIndex = *pdwSignerIndex;
3763 signerCert = CertFindCertificateInStore(store, X509_ASN_ENCODING,
3764 0, CERT_FIND_SUBJECT_CERT, signer, NULL);
3765 CryptMemFree(signer);
3768 else
3770 DWORD count, size = sizeof(count);
3772 if (CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_COUNT_PARAM, 0, &count,
3773 &size))
3775 for (i = 0; !signerCert && i < count; i++)
3777 CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg,
3780 if (signer)
3782 signerCert = CertFindCertificateInStore(store,
3783 X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, signer,
3784 NULL);
3785 if (signerCert)
3786 signerIndex = i;
3787 CryptMemFree(signer);
3791 if (!signerCert)
3792 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER);
3794 if (signerCert)
3796 if (!(dwFlags & CMSG_SIGNER_ONLY_FLAG))
3797 ret = CryptMsgControl(hCryptMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE,
3798 signerCert->pCertInfo);
3799 else
3800 ret = TRUE;
3801 if (ret)
3803 if (ppSigner)
3804 *ppSigner = CertDuplicateCertificateContext(signerCert);
3805 if (pdwSignerIndex)
3806 *pdwSignerIndex = signerIndex;
3808 CertFreeCertificateContext(signerCert);
3811 CertCloseStore(store, 0);
3812 return ret;
3815 BOOL WINAPI CryptMsgVerifyCountersignatureEncoded(HCRYPTPROV_LEGACY hCryptProv,
3816 DWORD dwEncodingType, BYTE *pbSignerInfo, DWORD cbSignerInfo,
3817 PBYTE pbSignerInfoCountersignature, DWORD cbSignerInfoCountersignature,
3818 CERT_INFO *pciCountersigner)
3820 FIXME("(%08Ix, %08lx, %p, %ld, %p, %ld, %p): stub\n", hCryptProv,
3821 dwEncodingType, pbSignerInfo, cbSignerInfo, pbSignerInfoCountersignature,
3822 cbSignerInfoCountersignature, pciCountersigner);
3823 return FALSE;
3826 BOOL WINAPI CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv,
3827 DWORD dwEncodingType, PBYTE pbSignerInfo, DWORD cbSignerInfo,
3828 PBYTE pbSignerInfoCountersignature, DWORD cbSignerInfoCountersignature,
3829 DWORD dwSignerType, void *pvSigner, DWORD dwFlags, void *pvReserved)
3831 FIXME("(%08Ix, %08lx, %p, %ld, %p, %ld, %ld, %p, %08lx, %p): stub\n", hCryptProv,
3832 dwEncodingType, pbSignerInfo, cbSignerInfo, pbSignerInfoCountersignature,
3833 cbSignerInfoCountersignature, dwSignerType, pvSigner, dwFlags, pvReserved);
3834 return FALSE;
3837 BOOL WINAPI CryptMsgEncodeAndSignCTL(DWORD dwMsgEncodingType,
3838 PCTL_INFO pCtlInfo, PCMSG_SIGNED_ENCODE_INFO pSignInfo, DWORD dwFlags,
3839 BYTE *pbEncoded, DWORD *pcbEncoded)
3841 BOOL ret;
3842 BYTE *pbCtlContent;
3843 DWORD cbCtlContent;
3845 TRACE("(%08lx, %p, %p, %08lx, %p, %p)\n", dwMsgEncodingType, pCtlInfo,
3846 pSignInfo, dwFlags, pbEncoded, pcbEncoded);
3848 if (dwFlags)
3850 FIXME("unimplemented for flags %08lx\n", dwFlags);
3851 return FALSE;
3853 if ((ret = CryptEncodeObjectEx(dwMsgEncodingType, PKCS_CTL, pCtlInfo,
3854 CRYPT_ENCODE_ALLOC_FLAG, NULL, &pbCtlContent, &cbCtlContent)))
3856 ret = CryptMsgSignCTL(dwMsgEncodingType, pbCtlContent, cbCtlContent,
3857 pSignInfo, dwFlags, pbEncoded, pcbEncoded);
3858 LocalFree(pbCtlContent);
3860 return ret;
3863 BOOL WINAPI CryptMsgSignCTL(DWORD dwMsgEncodingType, BYTE *pbCtlContent,
3864 DWORD cbCtlContent, PCMSG_SIGNED_ENCODE_INFO pSignInfo, DWORD dwFlags,
3865 BYTE *pbEncoded, DWORD *pcbEncoded)
3867 static char oid_ctl[] = szOID_CTL;
3868 BOOL ret;
3869 HCRYPTMSG msg;
3871 TRACE("(%08lx, %p, %ld, %p, %08lx, %p, %p)\n", dwMsgEncodingType,
3872 pbCtlContent, cbCtlContent, pSignInfo, dwFlags, pbEncoded, pcbEncoded);
3874 if (dwFlags)
3876 FIXME("unimplemented for flags %08lx\n", dwFlags);
3877 return FALSE;
3879 msg = CryptMsgOpenToEncode(dwMsgEncodingType, 0, CMSG_SIGNED, pSignInfo,
3880 oid_ctl, NULL);
3881 if (msg)
3883 ret = CryptMsgUpdate(msg, pbCtlContent, cbCtlContent, TRUE);
3884 if (ret)
3885 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbEncoded,
3886 pcbEncoded);
3887 CryptMsgClose(msg);
3889 else
3890 ret = FALSE;
3891 return ret;