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