source: trunk/src/crypt32/msg.c

Last change on this file was 21354, checked in by rlwalsh, 16 years ago

eliminate VACPP warning & info msgs - see Ticket #1

File size: 90.0 KB
Line 
1/*
2 * Copyright 2007 Juan Lang
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include "config.h"
20#include "wine/port.h"
21
22#include <stdarg.h>
23#include <string.h>
24#define NONAMELESSUNION
25#include "windef.h"
26#include "winbase.h"
27#include "wincrypt.h"
28#include "snmp.h"
29
30#include "wine/debug.h"
31#include "wine/exception.h"
32#include "crypt32_private.h"
33
34WINE_DEFAULT_DEBUG_CHANNEL(crypt);
35#define static
36/* Called when a message's ref count reaches zero. Free any message-specific
37 * data here.
38 */
39typedef void (*CryptMsgCloseFunc)(HCRYPTMSG msg);
40
41typedef BOOL (*CryptMsgGetParamFunc)(HCRYPTMSG hCryptMsg, DWORD dwParamType,
42 DWORD dwIndex, void *pvData, DWORD *pcbData);
43
44typedef BOOL (*CryptMsgUpdateFunc)(HCRYPTMSG hCryptMsg, const BYTE *pbData,
45 DWORD cbData, BOOL fFinal);
46
47typedef BOOL (*CryptMsgControlFunc)(HCRYPTMSG hCryptMsg, DWORD dwFlags,
48 DWORD dwCtrlType, const void *pvCtrlPara);
49
50static BOOL CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags,
51 DWORD dwCtrlType, const void *pvCtrlPara)
52{
53 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara);
54 SetLastError(E_INVALIDARG);
55 return FALSE;
56}
57
58typedef enum _CryptMsgState {
59 MsgStateInit,
60 MsgStateUpdated,
61 MsgStateDataFinalized,
62 MsgStateFinalized
63} CryptMsgState;
64
65typedef struct _CryptMsgBase
66{
67 LONG ref;
68 DWORD open_flags;
69 BOOL streamed;
70 CMSG_STREAM_INFO stream_info;
71 CryptMsgState state;
72 CryptMsgCloseFunc close;
73 CryptMsgUpdateFunc update;
74 CryptMsgGetParamFunc get_param;
75 CryptMsgControlFunc control;
76} CryptMsgBase;
77
78static inline void CryptMsgBase_Init(CryptMsgBase *msg, DWORD dwFlags,
79 PCMSG_STREAM_INFO pStreamInfo, CryptMsgCloseFunc close,
80 CryptMsgGetParamFunc get_param, CryptMsgUpdateFunc update,
81 CryptMsgControlFunc control)
82{
83 msg->ref = 1;
84 msg->open_flags = dwFlags;
85 if (pStreamInfo)
86 {
87 msg->streamed = TRUE;
88 msg->stream_info = *pStreamInfo;
89 }
90 else
91 {
92 msg->streamed = FALSE;
93 memset(&msg->stream_info, 0, sizeof(msg->stream_info));
94 }
95 msg->close = close;
96 msg->get_param = get_param;
97 msg->update = update;
98 msg->control = control;
99 msg->state = MsgStateInit;
100}
101
102typedef struct _CDataEncodeMsg
103{
104 CryptMsgBase base;
105 DWORD bare_content_len;
106 LPBYTE bare_content;
107} CDataEncodeMsg;
108
109static const BYTE empty_data_content[] = { 0x04,0x00 };
110
111static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg)
112{
113 CDataEncodeMsg *msg = (CDataEncodeMsg *)hCryptMsg;
114
115 if (msg->bare_content != empty_data_content)
116 LocalFree((HANDLE)msg->bare_content);
117}
118
119static BOOL WINAPI CRYPT_EncodeContentLength(DWORD dwCertEncodingType,
120 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
121 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
122{
123 DWORD dataLen = *(DWORD *)pvStructInfo;
124 DWORD lenBytes;
125 BOOL ret = TRUE;
126
127 /* Trick: report bytes needed based on total message length, even though
128 * the message isn't available yet. The caller will use the length
129 * reported here to encode its length.
130 */
131 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
132 if (!pbEncoded)
133 *pcbEncoded = 1 + lenBytes + dataLen;
134 else
135 {
136 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
137 pcbEncoded, 1 + lenBytes)) != FALSE)
138 {
139 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
140 pbEncoded = *(BYTE **)pbEncoded;
141 *pbEncoded++ = ASN_OCTETSTRING;
142 CRYPT_EncodeLen(dataLen, pbEncoded,
143 &lenBytes);
144 }
145 }
146 return ret;
147}
148
149static BOOL CRYPT_EncodeDataContentInfoHeader(CDataEncodeMsg *msg,
150 CRYPT_DATA_BLOB *header)
151{
152 BOOL ret;
153
154 if (msg->base.streamed && msg->base.stream_info.cbContent == 0xffffffff)
155 {
156 static const BYTE headerValue[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
157 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
158
159 header->pbData = (BYTE*)LocalAlloc(0, sizeof(headerValue));
160 if (header->pbData)
161 {
162 header->cbData = sizeof(headerValue);
163 memcpy(header->pbData, headerValue, sizeof(headerValue));
164 ret = TRUE;
165 }
166 else
167 ret = FALSE;
168 }
169 else
170 {
171 struct AsnConstructedItem constructed = { 0,
172 &msg->base.stream_info.cbContent, CRYPT_EncodeContentLength };
173 struct AsnEncodeSequenceItem items[2] = {
174 { szOID_RSA_data, CRYPT_AsnEncodeOid, 0 },
175 { &constructed, CRYPT_AsnEncodeConstructed, 0 },
176 };
177
178 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
179 sizeof(items) / sizeof(items[0]), CRYPT_ENCODE_ALLOC_FLAG, NULL,
180 (LPBYTE)&header->pbData, &header->cbData);
181 if (ret)
182 {
183 /* Trick: subtract the content length from the reported length,
184 * as the actual content hasn't come yet.
185 */
186 header->cbData -= msg->base.stream_info.cbContent;
187 }
188 }
189 return ret;
190}
191
192static BOOL CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
193 DWORD cbData, BOOL fFinal)
194{
195 CDataEncodeMsg *msg = (CDataEncodeMsg *)hCryptMsg;
196 BOOL ret = FALSE;
197
198 if (msg->base.state == MsgStateFinalized)
199 SetLastError(CRYPT_E_MSG_ERROR);
200 else if (msg->base.streamed)
201 {
202 __TRY
203 {
204 if (msg->base.state != MsgStateUpdated)
205 {
206 CRYPT_DATA_BLOB header;
207
208 ret = CRYPT_EncodeDataContentInfoHeader(msg, &header);
209 if (ret)
210 {
211 ret = msg->base.stream_info.pfnStreamOutput(
212 msg->base.stream_info.pvArg, header.pbData, header.cbData,
213 FALSE);
214 LocalFree((HANDLE)header.pbData);
215 }
216 }
217 /* Curiously, every indefinite-length streamed update appears to
218 * get its own tag and length, regardless of fFinal.
219 */
220 if (msg->base.stream_info.cbContent == 0xffffffff)
221 {
222 BYTE *header;
223 DWORD headerLen;
224
225 ret = CRYPT_EncodeContentLength(X509_ASN_ENCODING, NULL,
226 &cbData, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&header,
227 &headerLen);
228 if (ret)
229 {
230 ret = msg->base.stream_info.pfnStreamOutput(
231 msg->base.stream_info.pvArg, header, headerLen,
232 FALSE);
233 LocalFree((HANDLE)header);
234 }
235 }
236 if (!fFinal)
237 {
238 ret = msg->base.stream_info.pfnStreamOutput(
239 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData,
240 FALSE);
241 msg->base.state = MsgStateUpdated;
242 }
243 else
244 {
245 msg->base.state = MsgStateFinalized;
246 if (msg->base.stream_info.cbContent == 0xffffffff)
247 {
248 BYTE indefinite_trailer[6] = { 0 };
249
250 ret = msg->base.stream_info.pfnStreamOutput(
251 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData,
252 FALSE);
253 if (ret)
254 ret = msg->base.stream_info.pfnStreamOutput(
255 msg->base.stream_info.pvArg, indefinite_trailer,
256 sizeof(indefinite_trailer), TRUE);
257 }
258 else
259 ret = msg->base.stream_info.pfnStreamOutput(
260 msg->base.stream_info.pvArg, (BYTE *)pbData, cbData, TRUE);
261 }
262 }
263 __EXCEPT(1)
264 {
265 SetLastError(STATUS_ACCESS_VIOLATION);
266 ret = FALSE;
267 }
268 __ENDTRY;
269 }
270 else
271 {
272 if (!fFinal)
273 {
274 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
275 SetLastError(E_INVALIDARG);
276 else
277 SetLastError(CRYPT_E_MSG_ERROR);
278 }
279 else
280 {
281 msg->base.state = MsgStateFinalized;
282 if (!cbData)
283 SetLastError(E_INVALIDARG);
284 else
285 {
286 CRYPT_DATA_BLOB blob = { cbData, (LPBYTE)pbData };
287
288 /* non-streamed data messages don't allow non-final updates,
289 * don't bother checking whether data already exist, they can't.
290 */
291 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
292 &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL, &msg->bare_content,
293 &msg->bare_content_len);
294 }
295 }
296 }
297 return ret;
298}
299
300static BOOL CRYPT_CopyParam(void *pvData, DWORD *pcbData, const void *src,
301 DWORD len)
302{
303 BOOL ret = TRUE;
304
305 if (!pvData)
306 *pcbData = len;
307 else if (*pcbData < len)
308 {
309 *pcbData = len;
310 SetLastError(ERROR_MORE_DATA);
311 ret = FALSE;
312 }
313 else
314 {
315 *pcbData = len;
316 memcpy(pvData, src, len);
317 }
318 return ret;
319}
320
321static BOOL CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
322 DWORD dwIndex, void *pvData, DWORD *pcbData)
323{
324 CDataEncodeMsg *msg = (CDataEncodeMsg *)hCryptMsg;
325 BOOL ret = FALSE;
326
327 switch (dwParamType)
328 {
329 case CMSG_CONTENT_PARAM:
330 if (msg->base.streamed)
331 SetLastError(E_INVALIDARG);
332 else
333 {
334 CRYPT_CONTENT_INFO info;
335 char rsa_data[] = "1.2.840.113549.1.7.1";
336
337 info.pszObjId = rsa_data;
338 info.Content.cbData = msg->bare_content_len;
339 info.Content.pbData = msg->bare_content;
340 ret = CryptEncodeObject(X509_ASN_ENCODING, PKCS_CONTENT_INFO, &info,
341 pvData, pcbData);
342 }
343 break;
344 case CMSG_BARE_CONTENT_PARAM:
345 if (msg->base.streamed)
346 SetLastError(E_INVALIDARG);
347 else
348 ret = CRYPT_CopyParam(pvData, pcbData, msg->bare_content,
349 msg->bare_content_len);
350 break;
351 default:
352 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
353 }
354 return ret;
355}
356
357static HCRYPTMSG CDataEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
358 LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo)
359{
360 CDataEncodeMsg *msg;
361
362 if (pvMsgEncodeInfo)
363 {
364 SetLastError(E_INVALIDARG);
365 return NULL;
366 }
367 msg = CryptMemAlloc(sizeof(CDataEncodeMsg));
368 if (msg)
369 {
370 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo,
371 CDataEncodeMsg_Close, CDataEncodeMsg_GetParam, CDataEncodeMsg_Update,
372 CRYPT_DefaultMsgControl);
373 msg->bare_content_len = sizeof(empty_data_content);
374 msg->bare_content = (LPBYTE)empty_data_content;
375 }
376 return (HCRYPTMSG)msg;
377}
378
379typedef struct _CHashEncodeMsg
380{
381 CryptMsgBase base;
382 HCRYPTPROV prov;
383 HCRYPTHASH hash;
384 CRYPT_DATA_BLOB data;
385} CHashEncodeMsg;
386
387static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg)
388{
389 CHashEncodeMsg *msg = (CHashEncodeMsg *)hCryptMsg;
390
391 CryptMemFree(msg->data.pbData);
392 CryptDestroyHash(msg->hash);
393 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
394 CryptReleaseContext(msg->prov, 0);
395}
396
397static BOOL CRYPT_EncodePKCSDigestedData(CHashEncodeMsg *msg, void *pvData,
398 DWORD *pcbData)
399{
400 BOOL ret;
401 ALG_ID algID;
402 DWORD size = sizeof(algID);
403
404 ret = CryptGetHashParam(msg->hash, HP_ALGID, (BYTE *)&algID, &size, 0);
405 if (ret)
406 {
407 CRYPT_DIGESTED_DATA digestedData = { 0 };
408 char oid_rsa_data[] = szOID_RSA_data;
409
410 digestedData.version = CMSG_HASHED_DATA_PKCS_1_5_VERSION;
411 digestedData.DigestAlgorithm.pszObjId = (LPSTR)CertAlgIdToOID(algID);
412 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
413 /* Quirk: OID is only encoded messages if an update has happened */
414 if (msg->base.state != MsgStateInit)
415 digestedData.ContentInfo.pszObjId = oid_rsa_data;
416 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && msg->data.cbData)
417 {
418 ret = CRYPT_AsnEncodeOctets(0, NULL, &msg->data,
419 CRYPT_ENCODE_ALLOC_FLAG, NULL,
420 (LPBYTE)&digestedData.ContentInfo.Content.pbData,
421 &digestedData.ContentInfo.Content.cbData);
422 }
423 if (msg->base.state == MsgStateFinalized)
424 {
425 size = sizeof(DWORD);
426 ret = CryptGetHashParam(msg->hash, HP_HASHSIZE,
427 (LPBYTE)&digestedData.hash.cbData, &size, 0);
428 if (ret)
429 {
430 digestedData.hash.pbData = CryptMemAlloc(
431 digestedData.hash.cbData);
432 ret = CryptGetHashParam(msg->hash, HP_HASHVAL,
433 digestedData.hash.pbData, &digestedData.hash.cbData, 0);
434 }
435 }
436 if (ret)
437 ret = CRYPT_AsnEncodePKCSDigestedData(&digestedData, pvData,
438 pcbData);
439 CryptMemFree(digestedData.hash.pbData);
440 LocalFree((HANDLE)digestedData.ContentInfo.Content.pbData);
441 }
442 return ret;
443}
444
445static BOOL CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
446 DWORD dwIndex, void *pvData, DWORD *pcbData)
447{
448 CHashEncodeMsg *msg = (CHashEncodeMsg *)hCryptMsg;
449 BOOL ret = FALSE;
450
451 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex,
452 pvData, pcbData);
453
454 switch (dwParamType)
455 {
456 case CMSG_BARE_CONTENT_PARAM:
457 if (msg->base.streamed)
458 SetLastError(E_INVALIDARG);
459 else
460 ret = CRYPT_EncodePKCSDigestedData(msg, pvData, pcbData);
461 break;
462 case CMSG_CONTENT_PARAM:
463 {
464 CRYPT_CONTENT_INFO info;
465
466 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL,
467 &info.Content.cbData);
468 if (ret)
469 {
470 info.Content.pbData = CryptMemAlloc(info.Content.cbData);
471 if (info.Content.pbData)
472 {
473 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0,
474 info.Content.pbData, &info.Content.cbData);
475 if (ret)
476 {
477 char oid_rsa_hashed[] = szOID_RSA_hashedData;
478
479 info.pszObjId = oid_rsa_hashed;
480 ret = CryptEncodeObjectEx(X509_ASN_ENCODING,
481 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData);
482 }
483 CryptMemFree(info.Content.pbData);
484 }
485 else
486 ret = FALSE;
487 }
488 break;
489 }
490 case CMSG_COMPUTED_HASH_PARAM:
491 ret = CryptGetHashParam(msg->hash, HP_HASHVAL, (BYTE *)pvData, pcbData,
492 0);
493 break;
494 case CMSG_VERSION_PARAM:
495 if (msg->base.state != MsgStateFinalized)
496 SetLastError(CRYPT_E_MSG_ERROR);
497 else
498 {
499 DWORD version = CMSG_HASHED_DATA_PKCS_1_5_VERSION;
500
501 /* Since the data are always encoded as octets, the version is
502 * always 0 (see rfc3852, section 7)
503 */
504 ret = CRYPT_CopyParam(pvData, pcbData, &version, sizeof(version));
505 }
506 break;
507 default:
508 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
509 }
510 return ret;
511}
512
513static BOOL CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
514 DWORD cbData, BOOL fFinal)
515{
516 CHashEncodeMsg *msg = (CHashEncodeMsg *)hCryptMsg;
517 BOOL ret = FALSE;
518
519 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal);
520
521 if (msg->base.state == MsgStateFinalized)
522 SetLastError(CRYPT_E_MSG_ERROR);
523 else if (msg->base.streamed || (msg->base.open_flags & CMSG_DETACHED_FLAG))
524 {
525 /* Doesn't do much, as stream output is never called, and you
526 * can't get the content.
527 */
528 ret = CryptHashData(msg->hash, pbData, cbData, 0);
529 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated;
530 }
531 else
532 {
533 if (!fFinal)
534 SetLastError(CRYPT_E_MSG_ERROR);
535 else
536 {
537 ret = CryptHashData(msg->hash, pbData, cbData, 0);
538 if (ret)
539 {
540 msg->data.pbData = CryptMemAlloc(cbData);
541 if (msg->data.pbData)
542 {
543 memcpy(msg->data.pbData + msg->data.cbData, pbData, cbData);
544 msg->data.cbData += cbData;
545 }
546 else
547 ret = FALSE;
548 }
549 msg->base.state = MsgStateFinalized;
550 }
551 }
552 return ret;
553}
554
555static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
556 LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo)
557{
558 CHashEncodeMsg *msg;
559 const CMSG_HASHED_ENCODE_INFO *info =
560 (const CMSG_HASHED_ENCODE_INFO *)pvMsgEncodeInfo;
561 HCRYPTPROV prov;
562 ALG_ID algID;
563
564 if (info->cbSize != sizeof(CMSG_HASHED_ENCODE_INFO))
565 {
566 SetLastError(E_INVALIDARG);
567 return NULL;
568 }
569 if (!(algID = CertOIDToAlgId(info->HashAlgorithm.pszObjId)))
570 {
571 SetLastError(CRYPT_E_UNKNOWN_ALGO);
572 return NULL;
573 }
574 if (info->hCryptProv)
575 prov = info->hCryptProv;
576 else
577 {
578 prov = CRYPT_GetDefaultProvider();
579 dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
580 }
581 msg = CryptMemAlloc(sizeof(CHashEncodeMsg));
582 if (msg)
583 {
584 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo,
585 CHashEncodeMsg_Close, CHashEncodeMsg_GetParam, CHashEncodeMsg_Update,
586 CRYPT_DefaultMsgControl);
587 msg->prov = prov;
588 msg->data.cbData = 0;
589 msg->data.pbData = NULL;
590 if (!CryptCreateHash(prov, algID, 0, 0, &msg->hash))
591 {
592 CryptMsgClose(msg);
593 msg = NULL;
594 }
595 }
596 return (HCRYPTMSG)msg;
597}
598
599typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
600{
601 DWORD cbSize;
602 PCERT_INFO pCertInfo;
603 HCRYPTPROV hCryptProv;
604 DWORD dwKeySpec;
605 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
606 void *pvHashAuxInfo;
607 DWORD cAuthAttr;
608 PCRYPT_ATTRIBUTE rgAuthAttr;
609 DWORD cUnauthAttr;
610 PCRYPT_ATTRIBUTE rgUnauthAttr;
611 CERT_ID SignerId;
612 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
613 void *pvHashEncryptionAuxInfo;
614} CMSG_SIGNER_ENCODE_INFO_WITH_CMS, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS;
615
616typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
617{
618 DWORD cbSize;
619 DWORD cSigners;
620 PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners;
621 DWORD cCertEncoded;
622 PCERT_BLOB rgCertEncoded;
623 DWORD cCrlEncoded;
624 PCRL_BLOB rgCrlEncoded;
625 DWORD cAttrCertEncoded;
626 PCERT_BLOB rgAttrCertEncoded;
627} CMSG_SIGNED_ENCODE_INFO_WITH_CMS, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS;
628
629static BOOL CRYPT_IsValidSigner(CMSG_SIGNER_ENCODE_INFO_WITH_CMS *signer)
630{
631 if (signer->cbSize != sizeof(CMSG_SIGNER_ENCODE_INFO) &&
632 signer->cbSize != sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS))
633 {
634 SetLastError(E_INVALIDARG);
635 return FALSE;
636 }
637 if (signer->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO))
638 {
639 if (!signer->pCertInfo->SerialNumber.cbData)
640 {
641 SetLastError(E_INVALIDARG);
642 return FALSE;
643 }
644 if (!signer->pCertInfo->Issuer.cbData)
645 {
646 SetLastError(E_INVALIDARG);
647 return FALSE;
648 }
649 }
650 else if (signer->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS))
651 {
652 switch (signer->SignerId.dwIdChoice)
653 {
654 case 0:
655 if (!signer->pCertInfo->SerialNumber.cbData)
656 {
657 SetLastError(E_INVALIDARG);
658 return FALSE;
659 }
660 if (!signer->pCertInfo->Issuer.cbData)
661 {
662 SetLastError(E_INVALIDARG);
663 return FALSE;
664 }
665 break;
666 case CERT_ID_ISSUER_SERIAL_NUMBER:
667 if (!signer->SignerId.u.IssuerSerialNumber.SerialNumber.cbData)
668 {
669 SetLastError(E_INVALIDARG);
670 return FALSE;
671 }
672 if (!signer->SignerId.u.IssuerSerialNumber.Issuer.cbData)
673 {
674 SetLastError(E_INVALIDARG);
675 return FALSE;
676 }
677 break;
678 case CERT_ID_KEY_IDENTIFIER:
679 if (!signer->SignerId.u.KeyId.cbData)
680 {
681 SetLastError(E_INVALIDARG);
682 return FALSE;
683 }
684 break;
685 default:
686 SetLastError(E_INVALIDARG);
687 }
688 if (signer->HashEncryptionAlgorithm.pszObjId)
689 {
690 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
691 return FALSE;
692 }
693 }
694 if (!signer->hCryptProv)
695 {
696 SetLastError(E_INVALIDARG);
697 return FALSE;
698 }
699 if (!CertOIDToAlgId(signer->HashAlgorithm.pszObjId))
700 {
701 SetLastError(CRYPT_E_UNKNOWN_ALGO);
702 return FALSE;
703 }
704 return TRUE;
705}
706
707static BOOL CRYPT_ConstructBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in)
708{
709 BOOL ret = TRUE;
710
711 out->cbData = in->cbData;
712 if (out->cbData)
713 {
714 out->pbData = CryptMemAlloc(out->cbData);
715 if (out->pbData)
716 memcpy(out->pbData, in->pbData, out->cbData);
717 else
718 ret = FALSE;
719 }
720 else
721 out->pbData = NULL;
722 return ret;
723}
724
725typedef struct _BlobArray
726{
727 DWORD cBlobs;
728 PCRYPT_DATA_BLOB blobs;
729} BlobArray;
730
731static BOOL CRYPT_ConstructBlobArray(BlobArray *out, const BlobArray *in)
732{
733 BOOL ret = TRUE;
734
735 out->cBlobs = in->cBlobs;
736 if (out->cBlobs)
737 {
738 out->blobs = CryptMemAlloc(out->cBlobs * sizeof(CRYPT_DATA_BLOB));
739 if (out->blobs)
740 {
741 DWORD i;
742
743 memset(out->blobs, 0, out->cBlobs * sizeof(CRYPT_DATA_BLOB));
744 for (i = 0; ret && i < out->cBlobs; i++)
745 ret = CRYPT_ConstructBlob(&out->blobs[i], &in->blobs[i]);
746 }
747 else
748 ret = FALSE;
749 }
750 return ret;
751}
752
753static void CRYPT_FreeBlobArray(BlobArray *array)
754{
755 DWORD i;
756
757 for (i = 0; i < array->cBlobs; i++)
758 CryptMemFree(array->blobs[i].pbData);
759 CryptMemFree(array->blobs);
760}
761
762static BOOL CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE *out,
763 const CRYPT_ATTRIBUTE *in)
764{
765 BOOL ret;
766
767 out->pszObjId = CryptMemAlloc(strlen(in->pszObjId) + 1);
768 if (out->pszObjId)
769 {
770 strcpy(out->pszObjId, in->pszObjId);
771 ret = CRYPT_ConstructBlobArray((BlobArray *)&out->cValue,
772 (const BlobArray *)&in->cValue);
773 }
774 else
775 ret = FALSE;
776 return ret;
777}
778
779static BOOL CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES *out,
780 const CRYPT_ATTRIBUTES *in)
781{
782 BOOL ret = TRUE;
783
784 out->cAttr = in->cAttr;
785 if (out->cAttr)
786 {
787 out->rgAttr = CryptMemAlloc(out->cAttr * sizeof(CRYPT_ATTRIBUTE));
788 if (out->rgAttr)
789 {
790 DWORD i;
791
792 memset(out->rgAttr, 0, out->cAttr * sizeof(CRYPT_ATTRIBUTE));
793 for (i = 0; ret && i < out->cAttr; i++)
794 ret = CRYPT_ConstructAttribute(&out->rgAttr[i], &in->rgAttr[i]);
795 }
796 else
797 ret = FALSE;
798 }
799 else
800 out->rgAttr = NULL;
801 return ret;
802}
803
804/* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
805static BOOL CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO *info,
806 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS *in)
807{
808 BOOL ret;
809
810 if (in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO))
811 {
812 info->dwVersion = CMSG_SIGNER_INFO_V1;
813 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer,
814 &in->pCertInfo->Issuer);
815 if (ret)
816 ret = CRYPT_ConstructBlob(
817 &info->SignerId.u.IssuerSerialNumber.SerialNumber,
818 &in->pCertInfo->SerialNumber);
819 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
820 }
821 else
822 {
823 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS).
824 * See CRYPT_IsValidSigner.
825 */
826 if (!in->SignerId.dwIdChoice)
827 {
828 info->dwVersion = CMSG_SIGNER_INFO_V1;
829 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer,
830 &in->pCertInfo->Issuer);
831 if (ret)
832 ret = CRYPT_ConstructBlob(
833 &info->SignerId.u.IssuerSerialNumber.SerialNumber,
834 &in->pCertInfo->SerialNumber);
835 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
836 }
837 else if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
838 {
839 info->dwVersion = CMSG_SIGNER_INFO_V1;
840 info->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
841 ret = CRYPT_ConstructBlob(&info->SignerId.u.IssuerSerialNumber.Issuer,
842 &in->SignerId.u.IssuerSerialNumber.Issuer);
843 if (ret)
844 ret = CRYPT_ConstructBlob(
845 &info->SignerId.u.IssuerSerialNumber.SerialNumber,
846 &in->SignerId.u.IssuerSerialNumber.SerialNumber);
847 }
848 else
849 {
850 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */
851 info->dwVersion = CMSG_SIGNER_INFO_V3;
852 info->SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
853 ret = CRYPT_ConstructBlob(&info->SignerId.u.KeyId,
854 &in->SignerId.u.KeyId);
855 }
856 }
857 /* Assumption: algorithm IDs will point to static strings, not
858 * stack-based ones, so copying the pointer values is safe.
859 */
860 info->HashAlgorithm.pszObjId = in->HashAlgorithm.pszObjId;
861 if (ret)
862 ret = CRYPT_ConstructBlob(&info->HashAlgorithm.Parameters,
863 &in->HashAlgorithm.Parameters);
864 memset(&info->HashEncryptionAlgorithm, 0,
865 sizeof(info->HashEncryptionAlgorithm));
866 if (ret)
867 ret = CRYPT_ConstructAttributes(&info->AuthAttrs,
868 (CRYPT_ATTRIBUTES *)&in->cAuthAttr);
869 if (ret)
870 ret = CRYPT_ConstructAttributes(&info->UnauthAttrs,
871 (CRYPT_ATTRIBUTES *)&in->cUnauthAttr);
872 return ret;
873}
874
875static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO *info)
876{
877 DWORD i, j;
878
879 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
880 {
881 CryptMemFree(info->SignerId.u.IssuerSerialNumber.Issuer.pbData);
882 CryptMemFree(info->SignerId.u.IssuerSerialNumber.SerialNumber.pbData);
883 }
884 else
885 CryptMemFree(info->SignerId.u.KeyId.pbData);
886 CryptMemFree(info->HashAlgorithm.Parameters.pbData);
887 CryptMemFree(info->EncryptedHash.pbData);
888 for (i = 0; i < info->AuthAttrs.cAttr; i++)
889 {
890 for (j = 0; j < info->AuthAttrs.rgAttr[i].cValue; j++)
891 CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue[j].pbData);
892 CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue);
893 CryptMemFree(info->AuthAttrs.rgAttr[i].pszObjId);
894 }
895 CryptMemFree(info->AuthAttrs.rgAttr);
896 for (i = 0; i < info->UnauthAttrs.cAttr; i++)
897 {
898 for (j = 0; j < info->UnauthAttrs.rgAttr[i].cValue; j++)
899 CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue[j].pbData);
900 CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue);
901 CryptMemFree(info->UnauthAttrs.rgAttr[i].pszObjId);
902 }
903 CryptMemFree(info->UnauthAttrs.rgAttr);
904}
905
906typedef struct _CSignerHandles
907{
908 HCRYPTHASH contentHash;
909 HCRYPTHASH authAttrHash;
910} CSignerHandles;
911
912typedef struct _CSignedMsgData
913{
914 CRYPT_SIGNED_INFO *info;
915 DWORD cSignerHandle;
916 CSignerHandles *signerHandles;
917} CSignedMsgData;
918
919/* Constructs the signer handles for the signerIndex'th signer of msg_data.
920 * Assumes signerIndex is a valid idnex, and that msg_data's info has already
921 * been constructed.
922 */
923static BOOL CSignedMsgData_ConstructSignerHandles(CSignedMsgData *msg_data,
924 DWORD signerIndex, HCRYPTPROV crypt_prov)
925{
926 ALG_ID algID;
927 BOOL ret;
928
929 algID = CertOIDToAlgId(
930 msg_data->info->rgSignerInfo[signerIndex].HashAlgorithm.pszObjId);
931 ret = CryptCreateHash(crypt_prov, algID, 0, 0,
932 &msg_data->signerHandles->contentHash);
933 if (ret && msg_data->info->rgSignerInfo[signerIndex].AuthAttrs.cAttr > 0)
934 ret = CryptCreateHash(crypt_prov, algID, 0, 0,
935 &msg_data->signerHandles->authAttrHash);
936 return ret;
937}
938
939/* Allocates a CSignedMsgData's handles. Assumes its info has already been
940 * constructed.
941 */
942static BOOL CSignedMsgData_AllocateHandles(CSignedMsgData *msg_data)
943{
944 BOOL ret = TRUE;
945
946 if (msg_data->info->cSignerInfo)
947 {
948 msg_data->signerHandles =
949 CryptMemAlloc(msg_data->info->cSignerInfo * sizeof(CSignerHandles));
950 if (msg_data->signerHandles)
951 {
952 msg_data->cSignerHandle = msg_data->info->cSignerInfo;
953 memset(msg_data->signerHandles, 0,
954 msg_data->info->cSignerInfo * sizeof(CSignerHandles));
955 }
956 else
957 {
958 msg_data->cSignerHandle = 0;
959 ret = FALSE;
960 }
961 }
962 else
963 {
964 msg_data->cSignerHandle = 0;
965 msg_data->signerHandles = NULL;
966 }
967 return ret;
968}
969
970static void CSignedMsgData_CloseHandles(CSignedMsgData *msg_data)
971{
972 DWORD i;
973
974 for (i = 0; i < msg_data->cSignerHandle; i++)
975 {
976 if (msg_data->signerHandles[i].contentHash)
977 CryptDestroyHash(msg_data->signerHandles[i].contentHash);
978 if (msg_data->signerHandles[i].authAttrHash)
979 CryptDestroyHash(msg_data->signerHandles[i].authAttrHash);
980 }
981 CryptMemFree(msg_data->signerHandles);
982 msg_data->signerHandles = NULL;
983 msg_data->cSignerHandle = 0;
984}
985
986static BOOL CSignedMsgData_UpdateHash(CSignedMsgData *msg_data,
987 const BYTE *pbData, DWORD cbData)
988{
989 DWORD i;
990 BOOL ret = TRUE;
991
992 for (i = 0; ret && i < msg_data->cSignerHandle; i++)
993 ret = CryptHashData(msg_data->signerHandles[i].contentHash, pbData,
994 cbData, 0);
995 return ret;
996}
997
998static BOOL CRYPT_AppendAttribute(CRYPT_ATTRIBUTES *out,
999 const CRYPT_ATTRIBUTE *in)
1000{
1001 BOOL ret = FALSE;
1002
1003 out->rgAttr = CryptMemRealloc(out->rgAttr,
1004 (out->cAttr + 1) * sizeof(CRYPT_ATTRIBUTE));
1005 if (out->rgAttr)
1006 {
1007 ret = CRYPT_ConstructAttribute(&out->rgAttr[out->cAttr], in);
1008 if (ret)
1009 out->cAttr++;
1010 }
1011 return ret;
1012}
1013
1014static BOOL CSignedMsgData_AppendMessageDigestAttribute(
1015 CSignedMsgData *msg_data, DWORD signerIndex)
1016{
1017 BOOL ret;
1018 DWORD size;
1019 CRYPT_HASH_BLOB hash = { 0, NULL }, encodedHash = { 0, NULL };
1020 char messageDigest[] = szOID_RSA_messageDigest;
1021 CRYPT_ATTRIBUTE messageDigestAttr = { messageDigest, 1, &encodedHash };
1022
1023 size = sizeof(DWORD);
1024 ret = CryptGetHashParam(
1025 msg_data->signerHandles[signerIndex].contentHash, HP_HASHSIZE,
1026 (LPBYTE)&hash.cbData, &size, 0);
1027 if (ret)
1028 {
1029 hash.pbData = CryptMemAlloc(hash.cbData);
1030 ret = CryptGetHashParam(
1031 msg_data->signerHandles[signerIndex].contentHash, HP_HASHVAL,
1032 hash.pbData, &hash.cbData, 0);
1033 if (ret)
1034 {
1035 ret = CRYPT_AsnEncodeOctets(0, NULL, &hash, CRYPT_ENCODE_ALLOC_FLAG,
1036 NULL, (LPBYTE)&encodedHash.pbData, &encodedHash.cbData);
1037 if (ret)
1038 {
1039 ret = CRYPT_AppendAttribute(
1040 &msg_data->info->rgSignerInfo[signerIndex].AuthAttrs,
1041 &messageDigestAttr);
1042 LocalFree((HANDLE)encodedHash.pbData);
1043 }
1044 }
1045 CryptMemFree(hash.pbData);
1046 }
1047 return ret;
1048}
1049
1050typedef enum {
1051 Sign,
1052 Verify
1053} SignOrVerify;
1054
1055static BOOL CSignedMsgData_UpdateAuthenticatedAttributes(
1056 CSignedMsgData *msg_data, SignOrVerify flag)
1057{
1058 DWORD i;
1059 BOOL ret = TRUE;
1060
1061 TRACE("(%p)\n", msg_data);
1062
1063 for (i = 0; ret && i < msg_data->info->cSignerInfo; i++)
1064 {
1065 if (msg_data->info->rgSignerInfo[i].AuthAttrs.cAttr)
1066 {
1067 if (flag == Sign)
1068 {
1069 BYTE oid_rsa_data_encoded[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
1070 0xf7,0x0d,0x01,0x07,0x01 };
1071 CRYPT_DATA_BLOB content = { sizeof(oid_rsa_data_encoded),
1072 oid_rsa_data_encoded };
1073 char contentType[] = szOID_RSA_contentType;
1074 CRYPT_ATTRIBUTE contentTypeAttr = { contentType, 1, &content };
1075
1076 /* FIXME: does this depend on inner OID? */
1077 ret = CRYPT_AppendAttribute(
1078 &msg_data->info->rgSignerInfo[i].AuthAttrs, &contentTypeAttr);
1079 if (ret)
1080 ret = CSignedMsgData_AppendMessageDigestAttribute(msg_data,
1081 i);
1082 }
1083 if (ret)
1084 {
1085 LPBYTE encodedAttrs;
1086 DWORD size;
1087
1088 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, PKCS_ATTRIBUTES,
1089 &msg_data->info->rgSignerInfo[i].AuthAttrs,
1090 CRYPT_ENCODE_ALLOC_FLAG, NULL, (LPBYTE)&encodedAttrs, &size);
1091 if (ret)
1092 {
1093 ret = CryptHashData(
1094 msg_data->signerHandles[i].authAttrHash, encodedAttrs,
1095 size, 0);
1096 LocalFree((HANDLE)encodedAttrs);
1097 }
1098 }
1099 }
1100 }
1101 TRACE("returning %d\n", ret);
1102 return ret;
1103}
1104
1105static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB *hash)
1106{
1107 DWORD i;
1108 BYTE tmp;
1109
1110 for (i = 0; i < hash->cbData / 2; i++)
1111 {
1112 tmp = hash->pbData[hash->cbData - i - 1];
1113 hash->pbData[hash->cbData - i - 1] = hash->pbData[i];
1114 hash->pbData[i] = tmp;
1115 }
1116}
1117
1118static BOOL CSignedMsgData_Sign(CSignedMsgData *msg_data)
1119{
1120 DWORD i;
1121 BOOL ret = TRUE;
1122
1123 TRACE("(%p)\n", msg_data);
1124
1125 for (i = 0; ret && i < msg_data->info->cSignerInfo; i++)
1126 {
1127 HCRYPTHASH hash;
1128
1129 if (msg_data->info->rgSignerInfo[i].AuthAttrs.cAttr)
1130 hash = msg_data->signerHandles[i].authAttrHash;
1131 else
1132 hash = msg_data->signerHandles[i].contentHash;
1133 ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0, NULL,
1134 &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData);
1135 if (ret)
1136 {
1137 msg_data->info->rgSignerInfo[i].EncryptedHash.pbData =
1138 CryptMemAlloc(
1139 msg_data->info->rgSignerInfo[i].EncryptedHash.cbData);
1140 if (msg_data->info->rgSignerInfo[i].EncryptedHash.pbData)
1141 {
1142 ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0,
1143 msg_data->info->rgSignerInfo[i].EncryptedHash.pbData,
1144 &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData);
1145 if (ret)
1146 CRYPT_ReverseBytes(
1147 &msg_data->info->rgSignerInfo[i].EncryptedHash);
1148 }
1149 else
1150 ret = FALSE;
1151 }
1152 }
1153 return ret;
1154}
1155
1156static BOOL CSignedMsgData_Update(CSignedMsgData *msg_data,
1157 const BYTE *pbData, DWORD cbData, BOOL fFinal, SignOrVerify flag)
1158{
1159 BOOL ret = CSignedMsgData_UpdateHash(msg_data, pbData, cbData);
1160
1161 if (ret && fFinal)
1162 {
1163 ret = CSignedMsgData_UpdateAuthenticatedAttributes(msg_data, flag);
1164 if (ret && flag == Sign)
1165 ret = CSignedMsgData_Sign(msg_data);
1166 }
1167 return ret;
1168}
1169
1170typedef struct _CSignedEncodeMsg
1171{
1172 CryptMsgBase base;
1173 CRYPT_DATA_BLOB data;
1174 CSignedMsgData msg_data;
1175} CSignedEncodeMsg;
1176
1177static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg)
1178{
1179 CSignedEncodeMsg *msg = (CSignedEncodeMsg *)hCryptMsg;
1180 DWORD i;
1181
1182 CryptMemFree(msg->data.pbData);
1183 CRYPT_FreeBlobArray((BlobArray *)&msg->msg_data.info->cCertEncoded);
1184 CRYPT_FreeBlobArray((BlobArray *)&msg->msg_data.info->cCrlEncoded);
1185 for (i = 0; i < msg->msg_data.info->cSignerInfo; i++)
1186 CSignerInfo_Free(&msg->msg_data.info->rgSignerInfo[i]);
1187 CSignedMsgData_CloseHandles(&msg->msg_data);
1188 CryptMemFree(msg->msg_data.info->rgSignerInfo);
1189 CryptMemFree(msg->msg_data.info);
1190}
1191
1192static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
1193 DWORD dwIndex, void *pvData, DWORD *pcbData)
1194{
1195 CSignedEncodeMsg *msg = (CSignedEncodeMsg *)hCryptMsg;
1196 BOOL ret = FALSE;
1197
1198 switch (dwParamType)
1199 {
1200 case CMSG_CONTENT_PARAM:
1201 {
1202 CRYPT_CONTENT_INFO info;
1203
1204 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL,
1205 &info.Content.cbData);
1206 if (ret)
1207 {
1208 info.Content.pbData = CryptMemAlloc(info.Content.cbData);
1209 if (info.Content.pbData)
1210 {
1211 ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0,
1212 info.Content.pbData, &info.Content.cbData);
1213 if (ret)
1214 {
1215 char oid_rsa_signed[] = szOID_RSA_signedData;
1216
1217 info.pszObjId = oid_rsa_signed;
1218 ret = CryptEncodeObjectEx(X509_ASN_ENCODING,
1219 PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData);
1220 }
1221 CryptMemFree(info.Content.pbData);
1222 }
1223 else
1224 ret = FALSE;
1225 }
1226 break;
1227 }
1228 case CMSG_BARE_CONTENT_PARAM:
1229 {
1230 CRYPT_SIGNED_INFO info;
1231 char oid_rsa_data[] = szOID_RSA_data;
1232
1233 info = *msg->msg_data.info;
1234 /* Quirk: OID is only encoded messages if an update has happened */
1235 if (msg->base.state != MsgStateInit)
1236 info.content.pszObjId = oid_rsa_data;
1237 else
1238 info.content.pszObjId = NULL;
1239 if (msg->data.cbData)
1240 {
1241 CRYPT_DATA_BLOB blob = { msg->data.cbData, msg->data.pbData };
1242
1243 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
1244 &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL,
1245 &info.content.Content.pbData, &info.content.Content.cbData);
1246 }
1247 else
1248 {
1249 info.content.Content.cbData = 0;
1250 info.content.Content.pbData = NULL;
1251 ret = TRUE;
1252 }
1253 if (ret)
1254 {
1255 ret = CRYPT_AsnEncodeCMSSignedInfo(&info, pvData, pcbData);
1256 LocalFree((HANDLE)info.content.Content.pbData);
1257 }
1258 break;
1259 }
1260 case CMSG_COMPUTED_HASH_PARAM:
1261 if (dwIndex >= msg->msg_data.cSignerHandle)
1262 SetLastError(CRYPT_E_INVALID_INDEX);
1263 else
1264 ret = CryptGetHashParam(
1265 msg->msg_data.signerHandles[dwIndex].contentHash, HP_HASHVAL,
1266 pvData, pcbData, 0);
1267 break;
1268 case CMSG_ENCODED_SIGNER:
1269 if (dwIndex >= msg->msg_data.info->cSignerInfo)
1270 SetLastError(CRYPT_E_INVALID_INDEX);
1271 else
1272 ret = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1273 CMS_SIGNER_INFO, &msg->msg_data.info->rgSignerInfo[dwIndex], 0,
1274 NULL, pvData, pcbData);
1275 break;
1276 case CMSG_VERSION_PARAM:
1277 ret = CRYPT_CopyParam(pvData, pcbData, &msg->msg_data.info->version,
1278 sizeof(msg->msg_data.info->version));
1279 break;
1280 default:
1281 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
1282 }
1283 return ret;
1284}
1285
1286static BOOL CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
1287 DWORD cbData, BOOL fFinal)
1288{
1289 CSignedEncodeMsg *msg = (CSignedEncodeMsg *)hCryptMsg;
1290 BOOL ret = FALSE;
1291
1292 if (msg->base.state == MsgStateFinalized)
1293 SetLastError(CRYPT_E_MSG_ERROR);
1294 else if (msg->base.streamed || (msg->base.open_flags & CMSG_DETACHED_FLAG))
1295 {
1296 ret = CSignedMsgData_Update(&msg->msg_data, pbData, cbData, fFinal,
1297 Sign);
1298 if (msg->base.streamed)
1299 FIXME("streamed partial stub\n");
1300 msg->base.state = fFinal ? MsgStateFinalized : MsgStateUpdated;
1301 }
1302 else
1303 {
1304 if (!fFinal)
1305 SetLastError(CRYPT_E_MSG_ERROR);
1306 else
1307 {
1308 if (cbData)
1309 {
1310 msg->data.pbData = CryptMemAlloc(cbData);
1311 if (msg->data.pbData)
1312 {
1313 memcpy(msg->data.pbData, pbData, cbData);
1314 msg->data.cbData = cbData;
1315 ret = TRUE;
1316 }
1317 }
1318 else
1319 ret = TRUE;
1320 if (ret)
1321 ret = CSignedMsgData_Update(&msg->msg_data, pbData, cbData,
1322 fFinal, Sign);
1323 msg->base.state = MsgStateFinalized;
1324 }
1325 }
1326 return ret;
1327}
1328
1329static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags,
1330 const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID,
1331 PCMSG_STREAM_INFO pStreamInfo)
1332{
1333 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS *info =
1334 (const CMSG_SIGNED_ENCODE_INFO_WITH_CMS *)pvMsgEncodeInfo;
1335 DWORD i;
1336 CSignedEncodeMsg *msg;
1337
1338 if (info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO) &&
1339 info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS))
1340 {
1341 SetLastError(E_INVALIDARG);
1342 return NULL;
1343 }
1344 if (info->cbSize == sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS) &&
1345 info->cAttrCertEncoded)
1346 {
1347 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1348 return NULL;
1349 }
1350 for (i = 0; i < info->cSigners; i++)
1351 if (!CRYPT_IsValidSigner(&info->rgSigners[i]))
1352 return NULL;
1353 msg = CryptMemAlloc(sizeof(CSignedEncodeMsg));
1354 if (msg)
1355 {
1356 BOOL ret = TRUE;
1357
1358 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo,
1359 CSignedEncodeMsg_Close, CSignedEncodeMsg_GetParam,
1360 CSignedEncodeMsg_Update, CRYPT_DefaultMsgControl);
1361 msg->data.cbData = 0;
1362 msg->data.pbData = NULL;
1363 msg->msg_data.info = CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO));
1364 if (msg->msg_data.info)
1365 {
1366 memset(msg->msg_data.info, 0, sizeof(CRYPT_SIGNED_INFO));
1367 msg->msg_data.info->version = CMSG_SIGNED_DATA_V1;
1368 }
1369 else
1370 ret = FALSE;
1371 if (ret)
1372 {
1373 if (info->cSigners)
1374 {
1375 msg->msg_data.info->rgSignerInfo =
1376 CryptMemAlloc(info->cSigners * sizeof(CMSG_CMS_SIGNER_INFO));
1377 if (msg->msg_data.info->rgSignerInfo)
1378 {
1379 msg->msg_data.info->cSignerInfo = info->cSigners;
1380 memset(msg->msg_data.info->rgSignerInfo, 0,
1381 msg->msg_data.info->cSignerInfo *
1382 sizeof(CMSG_CMS_SIGNER_INFO));
1383 ret = CSignedMsgData_AllocateHandles(&msg->msg_data);
1384 for (i = 0; ret && i < msg->msg_data.info->cSignerInfo; i++)
1385 {
1386 if (info->rgSigners[i].SignerId.dwIdChoice ==
1387 CERT_ID_KEY_IDENTIFIER)
1388 msg->msg_data.info->version = CMSG_SIGNED_DATA_V3;
1389 ret = CSignerInfo_Construct(
1390 &msg->msg_data.info->rgSignerInfo[i],
1391 &info->rgSigners[i]);
1392 if (ret)
1393 {
1394 ret = CSignedMsgData_ConstructSignerHandles(
1395 &msg->msg_data, i, info->rgSigners[i].hCryptProv);
1396 if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
1397 CryptReleaseContext(info->rgSigners[i].hCryptProv,
1398 0);
1399 }
1400 }
1401 }
1402 else
1403 ret = FALSE;
1404 }
1405 else
1406 {
1407 msg->msg_data.info->cSignerInfo = 0;
1408 msg->msg_data.signerHandles = NULL;
1409 msg->msg_data.cSignerHandle = 0;
1410 }
1411 }
1412 if (ret)
1413 ret = CRYPT_ConstructBlobArray(
1414 (BlobArray *)&msg->msg_data.info->cCertEncoded,
1415 (const BlobArray *)&info->cCertEncoded);
1416 if (ret)
1417 ret = CRYPT_ConstructBlobArray(
1418 (BlobArray *)&msg->msg_data.info->cCrlEncoded,
1419 (const BlobArray *)&info->cCrlEncoded);
1420 if (!ret)
1421 {
1422 CSignedEncodeMsg_Close(msg);
1423 msg = NULL;
1424 }
1425 }
1426 return msg;
1427}
1428
1429HCRYPTMSG WINAPI CryptMsgOpenToEncode(DWORD dwMsgEncodingType, DWORD dwFlags,
1430 DWORD dwMsgType, const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID,
1431 PCMSG_STREAM_INFO pStreamInfo)
1432{
1433 HCRYPTMSG msg = NULL;
1434
1435 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType, dwFlags,
1436 dwMsgType, pvMsgEncodeInfo, debugstr_a(pszInnerContentObjID), pStreamInfo);
1437
1438 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING)
1439 {
1440 SetLastError(E_INVALIDARG);
1441 return NULL;
1442 }
1443 switch (dwMsgType)
1444 {
1445 case CMSG_DATA:
1446 msg = CDataEncodeMsg_Open(dwFlags, pvMsgEncodeInfo,
1447 pszInnerContentObjID, pStreamInfo);
1448 break;
1449 case CMSG_HASHED:
1450 msg = CHashEncodeMsg_Open(dwFlags, pvMsgEncodeInfo,
1451 pszInnerContentObjID, pStreamInfo);
1452 break;
1453 case CMSG_SIGNED:
1454 msg = CSignedEncodeMsg_Open(dwFlags, pvMsgEncodeInfo,
1455 pszInnerContentObjID, pStreamInfo);
1456 break;
1457 case CMSG_ENVELOPED:
1458 FIXME("unimplemented for type CMSG_ENVELOPED\n");
1459 break;
1460 case CMSG_SIGNED_AND_ENVELOPED:
1461 case CMSG_ENCRYPTED:
1462 /* defined but invalid, fall through */
1463 default:
1464 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
1465 }
1466 return msg;
1467}
1468
1469typedef struct _CDecodeMsg
1470{
1471 CryptMsgBase base;
1472 DWORD type;
1473 HCRYPTPROV crypt_prov;
1474 union {
1475 HCRYPTHASH hash;
1476 CSignedMsgData signed_data;
1477 } u;
1478 CRYPT_DATA_BLOB msg_data;
1479 CRYPT_DATA_BLOB detached_data;
1480 PCONTEXT_PROPERTY_LIST properties;
1481} CDecodeMsg;
1482
1483static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg)
1484{
1485 CDecodeMsg *msg = (CDecodeMsg *)hCryptMsg;
1486
1487 if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
1488 CryptReleaseContext(msg->crypt_prov, 0);
1489 switch (msg->type)
1490 {
1491 case CMSG_HASHED:
1492 if (msg->u.hash)
1493 CryptDestroyHash(msg->u.hash);
1494 break;
1495 case CMSG_SIGNED:
1496 if (msg->u.signed_data.info)
1497 {
1498 LocalFree((HANDLE)msg->u.signed_data.info);
1499 CSignedMsgData_CloseHandles(&msg->u.signed_data);
1500 }
1501 break;
1502 }
1503 CryptMemFree(msg->msg_data.pbData);
1504 CryptMemFree(msg->detached_data.pbData);
1505 ContextPropertyList_Free(msg->properties);
1506}
1507
1508static BOOL CDecodeMsg_CopyData(CRYPT_DATA_BLOB *blob, const BYTE *pbData,
1509 DWORD cbData)
1510{
1511 BOOL ret = TRUE;
1512
1513 if (cbData)
1514 {
1515 if (blob->cbData)
1516 blob->pbData = CryptMemRealloc(blob->pbData,
1517 blob->cbData + cbData);
1518 else
1519 blob->pbData = CryptMemAlloc(cbData);
1520 if (blob->pbData)
1521 {
1522 memcpy(blob->pbData + blob->cbData, pbData, cbData);
1523 blob->cbData += cbData;
1524 }
1525 else
1526 ret = FALSE;
1527 }
1528 return ret;
1529}
1530
1531static BOOL CDecodeMsg_DecodeDataContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob)
1532{
1533 BOOL ret;
1534 CRYPT_DATA_BLOB *data;
1535 DWORD size;
1536
1537 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
1538 blob->pbData, blob->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, (LPBYTE)&data,
1539 &size);
1540 if (ret)
1541 {
1542 ret = ContextPropertyList_SetProperty(msg->properties,
1543 CMSG_CONTENT_PARAM, data->pbData, data->cbData);
1544 LocalFree((HANDLE)data);
1545 }
1546 return ret;
1547}
1548
1549static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg *msg, DWORD param,
1550 const CRYPT_ALGORITHM_IDENTIFIER *id)
1551{
1552 static const BYTE nullParams[] = { ASN_NULL, 0 };
1553 CRYPT_ALGORITHM_IDENTIFIER *copy;
1554 DWORD len = sizeof(CRYPT_ALGORITHM_IDENTIFIER);
1555
1556 /* Linearize algorithm id */
1557 len += strlen(id->pszObjId) + 1;
1558 len += id->Parameters.cbData;
1559 copy = CryptMemAlloc(len);
1560 if (copy)
1561 {
1562 copy->pszObjId =
1563 (LPSTR)((BYTE *)copy + sizeof(CRYPT_ALGORITHM_IDENTIFIER));
1564 strcpy(copy->pszObjId, id->pszObjId);
1565 copy->Parameters.pbData = (BYTE *)copy->pszObjId + strlen(id->pszObjId)
1566 + 1;
1567 /* Trick: omit NULL parameters */
1568 if (id->Parameters.cbData == sizeof(nullParams) &&
1569 !memcmp(id->Parameters.pbData, nullParams, sizeof(nullParams)))
1570 {
1571 copy->Parameters.cbData = 0;
1572 len -= sizeof(nullParams);
1573 }
1574 else
1575 copy->Parameters.cbData = id->Parameters.cbData;
1576 if (copy->Parameters.cbData)
1577 memcpy(copy->Parameters.pbData, id->Parameters.pbData,
1578 id->Parameters.cbData);
1579 ContextPropertyList_SetProperty(msg->properties, param, (BYTE *)copy,
1580 len);
1581 CryptMemFree(copy);
1582 }
1583}
1584
1585static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER *id)
1586{
1587 id->pszObjId = (LPSTR)((BYTE *)id + sizeof(CRYPT_ALGORITHM_IDENTIFIER));
1588 id->Parameters.pbData = (BYTE *)id->pszObjId + strlen(id->pszObjId) + 1;
1589}
1590
1591static BOOL CDecodeMsg_DecodeHashedContent(CDecodeMsg *msg,
1592 CRYPT_DER_BLOB *blob)
1593{
1594 BOOL ret;
1595 CRYPT_DIGESTED_DATA *digestedData;
1596 DWORD size;
1597
1598 ret = CRYPT_AsnDecodePKCSDigestedData(blob->pbData, blob->cbData,
1599 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_DIGESTED_DATA *)&digestedData,
1600 &size);
1601 if (ret)
1602 {
1603 ContextPropertyList_SetProperty(msg->properties, CMSG_VERSION_PARAM,
1604 (const BYTE *)&digestedData->version, sizeof(digestedData->version));
1605 CDecodeMsg_SaveAlgorithmID(msg, CMSG_HASH_ALGORITHM_PARAM,
1606 &digestedData->DigestAlgorithm);
1607 ContextPropertyList_SetProperty(msg->properties,
1608 CMSG_INNER_CONTENT_TYPE_PARAM,
1609 (const BYTE *)digestedData->ContentInfo.pszObjId,
1610 digestedData->ContentInfo.pszObjId ?
1611 strlen(digestedData->ContentInfo.pszObjId) + 1 : 0);
1612 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG))
1613 {
1614 if (digestedData->ContentInfo.Content.cbData)
1615 CDecodeMsg_DecodeDataContent(msg,
1616 &digestedData->ContentInfo.Content);
1617 else
1618 ContextPropertyList_SetProperty(msg->properties,
1619 CMSG_CONTENT_PARAM, NULL, 0);
1620 }
1621 ContextPropertyList_SetProperty(msg->properties, CMSG_HASH_DATA_PARAM,
1622 digestedData->hash.pbData, digestedData->hash.cbData);
1623 LocalFree((HANDLE)digestedData);
1624 }
1625 return ret;
1626}
1627
1628static BOOL CDecodeMsg_DecodeSignedContent(CDecodeMsg *msg,
1629 CRYPT_DER_BLOB *blob)
1630{
1631 BOOL ret;
1632 CRYPT_SIGNED_INFO *signedInfo;
1633 DWORD size;
1634
1635 ret = CRYPT_AsnDecodeCMSSignedInfo(blob->pbData, blob->cbData,
1636 CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_SIGNED_INFO *)&signedInfo,
1637 &size);
1638 if (ret)
1639 msg->u.signed_data.info = signedInfo;
1640 return ret;
1641}
1642
1643/* Decodes the content in blob as the type given, and updates the value
1644 * (type, parameters, etc.) of msg based on what blob contains.
1645 * It doesn't just use msg's type, to allow a recursive call from an implicitly
1646 * typed message once the outer content info has been decoded.
1647 */
1648static BOOL CDecodeMsg_DecodeContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob,
1649 DWORD type)
1650{
1651 BOOL ret;
1652
1653 switch (type)
1654 {
1655 case CMSG_DATA:
1656 if ((ret = CDecodeMsg_DecodeDataContent(msg, blob)) != FALSE)
1657 msg->type = CMSG_DATA;
1658 break;
1659 case CMSG_HASHED:
1660 if ((ret = CDecodeMsg_DecodeHashedContent(msg, blob)) != FALSE)
1661 msg->type = CMSG_HASHED;
1662 break;
1663 case CMSG_ENVELOPED:
1664 FIXME("unimplemented for type CMSG_ENVELOPED\n");
1665 ret = TRUE;
1666 break;
1667 case CMSG_SIGNED:
1668 if ((ret = CDecodeMsg_DecodeSignedContent(msg, blob)) != FALSE)
1669 msg->type = CMSG_SIGNED;
1670 break;
1671 default:
1672 {
1673 CRYPT_CONTENT_INFO *info;
1674 DWORD size;
1675
1676 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, PKCS_CONTENT_INFO,
1677 msg->msg_data.pbData, msg->msg_data.cbData, CRYPT_DECODE_ALLOC_FLAG,
1678 NULL, (LPBYTE)&info, &size);
1679 if (ret)
1680 {
1681 if (!strcmp(info->pszObjId, szOID_RSA_data))
1682 ret = CDecodeMsg_DecodeContent(msg, &info->Content, CMSG_DATA);
1683 else if (!strcmp(info->pszObjId, szOID_RSA_digestedData))
1684 ret = CDecodeMsg_DecodeContent(msg, &info->Content,
1685 CMSG_HASHED);
1686 else if (!strcmp(info->pszObjId, szOID_RSA_envelopedData))
1687 ret = CDecodeMsg_DecodeContent(msg, &info->Content,
1688 CMSG_ENVELOPED);
1689 else if (!strcmp(info->pszObjId, szOID_RSA_signedData))
1690 ret = CDecodeMsg_DecodeContent(msg, &info->Content,
1691 CMSG_SIGNED);
1692 else
1693 {
1694 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
1695 ret = FALSE;
1696 }
1697 LocalFree((HANDLE)info);
1698 }
1699 }
1700 }
1701 return ret;
1702}
1703
1704static BOOL CDecodeMsg_FinalizeHashedContent(CDecodeMsg *msg,
1705 CRYPT_DER_BLOB *blob)
1706{
1707 CRYPT_ALGORITHM_IDENTIFIER *hashAlgoID = NULL;
1708 DWORD size = 0;
1709 ALG_ID algID = 0;
1710 BOOL ret;
1711
1712 CryptMsgGetParam(msg, CMSG_HASH_ALGORITHM_PARAM, 0, NULL, &size);
1713 hashAlgoID = CryptMemAlloc(size);
1714 ret = CryptMsgGetParam(msg, CMSG_HASH_ALGORITHM_PARAM, 0, hashAlgoID,
1715 &size);
1716 if (ret)
1717 algID = CertOIDToAlgId(hashAlgoID->pszObjId);
1718 ret = CryptCreateHash(msg->crypt_prov, algID, 0, 0, &msg->u.hash);
1719 if (ret)
1720 {
1721 CRYPT_DATA_BLOB content;
1722
1723 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
1724 {
1725 /* Unlike for non-detached messages, the data were never stored as
1726 * the content param, but were saved in msg->detached_data instead.
1727 */
1728 content.pbData = msg->detached_data.pbData;
1729 content.cbData = msg->detached_data.cbData;
1730 }
1731 else
1732 ret = ContextPropertyList_FindProperty(msg->properties,
1733 CMSG_CONTENT_PARAM, &content);
1734 if (ret)
1735 ret = CryptHashData(msg->u.hash, content.pbData, content.cbData, 0);
1736 }
1737 CryptMemFree(hashAlgoID);
1738 return ret;
1739}
1740
1741static BOOL CDecodeMsg_FinalizeSignedContent(CDecodeMsg *msg,
1742 CRYPT_DER_BLOB *blob)
1743{
1744 BOOL ret;
1745 DWORD i, size;
1746
1747 ret = CSignedMsgData_AllocateHandles(&msg->u.signed_data);
1748 for (i = 0; ret && i < msg->u.signed_data.info->cSignerInfo; i++)
1749 ret = CSignedMsgData_ConstructSignerHandles(&msg->u.signed_data, i,
1750 msg->crypt_prov);
1751 if (ret)
1752 {
1753 CRYPT_DATA_BLOB *content;
1754
1755 /* Now that we have all the content, update the hash handles with
1756 * it. If the message is a detached message, the content is stored
1757 * in msg->detached_data rather than in the signed message's
1758 * content.
1759 */
1760 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
1761 content = &msg->detached_data;
1762 else
1763 content = &msg->u.signed_data.info->content.Content;
1764 if (content->cbData)
1765 {
1766 /* If the message is not detached, have to decode the message's
1767 * content if the type is szOID_RSA_data.
1768 */
1769 if (!(msg->base.open_flags & CMSG_DETACHED_FLAG) &&
1770 !strcmp(msg->u.signed_data.info->content.pszObjId,
1771 szOID_RSA_data))
1772 {
1773 CRYPT_DATA_BLOB *blob;
1774
1775 ret = CryptDecodeObjectEx(X509_ASN_ENCODING,
1776 X509_OCTET_STRING, content->pbData, content->cbData,
1777 CRYPT_DECODE_ALLOC_FLAG, NULL, (LPBYTE)&blob, &size);
1778 if (ret)
1779 {
1780 ret = CSignedMsgData_Update(&msg->u.signed_data,
1781 blob->pbData, blob->cbData, TRUE, Verify);
1782 LocalFree((HANDLE)blob);
1783 }
1784 }
1785 else
1786 ret = CSignedMsgData_Update(&msg->u.signed_data,
1787 content->pbData, content->cbData, TRUE, Verify);
1788 }
1789 }
1790 return ret;
1791}
1792
1793static BOOL CDecodeMsg_FinalizeContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob)
1794{
1795 BOOL ret = FALSE;
1796
1797 switch (msg->type)
1798 {
1799 case CMSG_HASHED:
1800 ret = CDecodeMsg_FinalizeHashedContent(msg, blob);
1801 break;
1802 case CMSG_SIGNED:
1803 ret = CDecodeMsg_FinalizeSignedContent(msg, blob);
1804 break;
1805 default:
1806 ret = TRUE;
1807 }
1808 return ret;
1809}
1810
1811static BOOL CDecodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
1812 DWORD cbData, BOOL fFinal)
1813{
1814 CDecodeMsg *msg = (CDecodeMsg *)hCryptMsg;
1815 BOOL ret = FALSE;
1816
1817 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal);
1818
1819 if (msg->base.state == MsgStateFinalized)
1820 SetLastError(CRYPT_E_MSG_ERROR);
1821 else if (msg->base.streamed)
1822 {
1823 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg, pbData,
1824 cbData, fFinal);
1825 switch (msg->base.state)
1826 {
1827 case MsgStateInit:
1828 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData);
1829 if (fFinal)
1830 {
1831 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
1832 msg->base.state = MsgStateDataFinalized;
1833 else
1834 msg->base.state = MsgStateFinalized;
1835 }
1836 else
1837 msg->base.state = MsgStateUpdated;
1838 break;
1839 case MsgStateUpdated:
1840 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData);
1841 if (fFinal)
1842 {
1843 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
1844 msg->base.state = MsgStateDataFinalized;
1845 else
1846 msg->base.state = MsgStateFinalized;
1847 }
1848 break;
1849 case MsgStateDataFinalized:
1850 ret = CDecodeMsg_CopyData(&msg->detached_data, pbData, cbData);
1851 if (fFinal)
1852 msg->base.state = MsgStateFinalized;
1853 break;
1854 default:
1855 SetLastError(CRYPT_E_MSG_ERROR);
1856 break;
1857 }
1858 }
1859 else
1860 {
1861 if (!fFinal)
1862 SetLastError(CRYPT_E_MSG_ERROR);
1863 else
1864 {
1865 switch (msg->base.state)
1866 {
1867 case MsgStateInit:
1868 ret = CDecodeMsg_CopyData(&msg->msg_data, pbData, cbData);
1869 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
1870 msg->base.state = MsgStateDataFinalized;
1871 else
1872 msg->base.state = MsgStateFinalized;
1873 break;
1874 case MsgStateDataFinalized:
1875 ret = CDecodeMsg_CopyData(&msg->detached_data, pbData, cbData);
1876 msg->base.state = MsgStateFinalized;
1877 break;
1878 default:
1879 SetLastError(CRYPT_E_MSG_ERROR);
1880 }
1881 }
1882 }
1883 if (ret && fFinal &&
1884 ((msg->base.open_flags & CMSG_DETACHED_FLAG && msg->base.state ==
1885 MsgStateDataFinalized) ||
1886 (!(msg->base.open_flags & CMSG_DETACHED_FLAG) && msg->base.state ==
1887 MsgStateFinalized)))
1888 ret = CDecodeMsg_DecodeContent(msg, &msg->msg_data, msg->type);
1889 if (ret && msg->base.state == MsgStateFinalized)
1890 ret = CDecodeMsg_FinalizeContent(msg, &msg->msg_data);
1891 return ret;
1892}
1893
1894static BOOL CDecodeHashMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType,
1895 DWORD dwIndex, void *pvData, DWORD *pcbData)
1896{
1897 BOOL ret = FALSE;
1898
1899 switch (dwParamType)
1900 {
1901 case CMSG_TYPE_PARAM:
1902 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type));
1903 break;
1904 case CMSG_HASH_ALGORITHM_PARAM:
1905 {
1906 CRYPT_DATA_BLOB blob;
1907
1908 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType,
1909 &blob);
1910 if (ret)
1911 {
1912 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, blob.cbData);
1913 if (ret && pvData)
1914 CRYPT_FixUpAlgorithmID((CRYPT_ALGORITHM_IDENTIFIER *)pvData);
1915 }
1916 else
1917 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
1918 break;
1919 }
1920 case CMSG_COMPUTED_HASH_PARAM:
1921 ret = CryptGetHashParam(msg->u.hash, HP_HASHVAL, pvData, pcbData, 0);
1922 break;
1923 default:
1924 {
1925 CRYPT_DATA_BLOB blob;
1926
1927 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType,
1928 &blob);
1929 if (ret)
1930 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData, blob.cbData);
1931 else
1932 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
1933 }
1934 }
1935 return ret;
1936}
1937
1938/* nextData is an in/out parameter - on input it's the memory location in
1939 * which a copy of in's data should be made, and on output it's the memory
1940 * location immediately after out's copy of in's data.
1941 */
1942static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB *out,
1943 const CRYPT_DATA_BLOB *in, LPBYTE *nextData)
1944{
1945 out->cbData = in->cbData;
1946 if (in->cbData)
1947 {
1948 out->pbData = *nextData;
1949 memcpy(out->pbData, in->pbData, in->cbData);
1950 *nextData += in->cbData;
1951 }
1952}
1953
1954static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER *out,
1955 const CRYPT_ALGORITHM_IDENTIFIER *in, LPBYTE *nextData)
1956{
1957 if (in->pszObjId)
1958 {
1959 out->pszObjId = (LPSTR)*nextData;
1960 strcpy(out->pszObjId, in->pszObjId);
1961 *nextData += strlen(out->pszObjId) + 1;
1962 }
1963 CRYPT_CopyBlob(&out->Parameters, &in->Parameters, nextData);
1964}
1965
1966static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out,
1967 const CRYPT_ATTRIBUTES *in, LPBYTE *nextData)
1968{
1969 out->cAttr = in->cAttr;
1970 if (in->cAttr)
1971 {
1972 DWORD i;
1973
1974 *nextData = POINTER_ALIGN_DWORD_PTR(*nextData);
1975 out->rgAttr = (CRYPT_ATTRIBUTE *)*nextData;
1976 *nextData += in->cAttr * sizeof(CRYPT_ATTRIBUTE);
1977 for (i = 0; i < in->cAttr; i++)
1978 {
1979 if (in->rgAttr[i].pszObjId)
1980 {
1981 out->rgAttr[i].pszObjId = (LPSTR)*nextData;
1982 strcpy(out->rgAttr[i].pszObjId, in->rgAttr[i].pszObjId);
1983 *nextData += strlen(in->rgAttr[i].pszObjId) + 1;
1984 }
1985 if (in->rgAttr[i].cValue)
1986 {
1987 DWORD j;
1988
1989 out->rgAttr[i].cValue = in->rgAttr[i].cValue;
1990 *nextData = POINTER_ALIGN_DWORD_PTR(*nextData);
1991 out->rgAttr[i].rgValue = (PCRYPT_DATA_BLOB)*nextData;
1992 *nextData += in->rgAttr[i].cValue * sizeof(CRYPT_DATA_BLOB);
1993 for (j = 0; j < in->rgAttr[i].cValue; j++)
1994 CRYPT_CopyBlob(&out->rgAttr[i].rgValue[j],
1995 &in->rgAttr[i].rgValue[j], nextData);
1996 }
1997 }
1998 }
1999}
2000
2001static DWORD CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES *attr)
2002{
2003 DWORD size = attr->cAttr * sizeof(CRYPT_ATTRIBUTE), i, j;
2004
2005 for (i = 0; i < attr->cAttr; i++)
2006 {
2007 if (attr->rgAttr[i].pszObjId)
2008 size += strlen(attr->rgAttr[i].pszObjId) + 1;
2009 /* align pointer */
2010 size = ALIGN_DWORD_PTR(size);
2011 size += attr->rgAttr[i].cValue * sizeof(CRYPT_DATA_BLOB);
2012 for (j = 0; j < attr->rgAttr[i].cValue; j++)
2013 size += attr->rgAttr[i].rgValue[j].cbData;
2014 }
2015 /* align pointer again to be conservative */
2016 size = ALIGN_DWORD_PTR(size);
2017 return size;
2018}
2019
2020static DWORD CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB *keyId)
2021{
2022 static char oid_key_rdn[] = szOID_KEYID_RDN;
2023 DWORD size = 0;
2024 CERT_RDN_ATTR attr;
2025 CERT_RDN rdn = { 1, &attr };
2026 CERT_NAME_INFO name = { 1, &rdn };
2027
2028 attr.pszObjId = oid_key_rdn;
2029 attr.dwValueType = CERT_RDN_OCTET_STRING;
2030 attr.Value.cbData = keyId->cbData;
2031 attr.Value.pbData = keyId->pbData;
2032 if (CryptEncodeObject(X509_ASN_ENCODING, X509_NAME, &name, NULL, &size))
2033 size++; /* Only include size of special zero serial number on success */
2034 return size;
2035}
2036
2037static BOOL CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB *issuer,
2038 CRYPT_INTEGER_BLOB *serialNumber, const CRYPT_DATA_BLOB *keyId, DWORD encodedLen,
2039 LPBYTE *nextData)
2040{
2041 static char oid_key_rdn[] = szOID_KEYID_RDN;
2042 CERT_RDN_ATTR attr;
2043 CERT_RDN rdn = { 1, &attr };
2044 CERT_NAME_INFO name = { 1, &rdn };
2045 BOOL ret;
2046
2047 /* Encode special zero serial number */
2048 serialNumber->cbData = 1;
2049 serialNumber->pbData = *nextData;
2050 **nextData = 0;
2051 (*nextData)++;
2052 /* Encode issuer */
2053 issuer->pbData = *nextData;
2054 attr.pszObjId = oid_key_rdn;
2055 attr.dwValueType = CERT_RDN_OCTET_STRING;
2056 attr.Value.cbData = keyId->cbData;
2057 attr.Value.pbData = keyId->pbData;
2058 ret = CryptEncodeObject(X509_ASN_ENCODING, X509_NAME, &name, *nextData,
2059 &encodedLen);
2060 if (ret)
2061 {
2062 *nextData += encodedLen;
2063 issuer->cbData = encodedLen;
2064 }
2065 return ret;
2066}
2067
2068static BOOL CRYPT_CopySignerInfo(void *pvData, DWORD *pcbData,
2069 const CMSG_CMS_SIGNER_INFO *in)
2070{
2071 DWORD size = sizeof(CMSG_SIGNER_INFO), rdnSize = 0;
2072 BOOL ret;
2073
2074 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in);
2075
2076 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2077 {
2078 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData;
2079 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData;
2080 }
2081 else
2082 {
2083 rdnSize = CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in->SignerId.u.KeyId);
2084 size += rdnSize;
2085 }
2086 if (in->HashAlgorithm.pszObjId)
2087 size += strlen(in->HashAlgorithm.pszObjId) + 1;
2088 size += in->HashAlgorithm.Parameters.cbData;
2089 if (in->HashEncryptionAlgorithm.pszObjId)
2090 size += strlen(in->HashEncryptionAlgorithm.pszObjId) + 1;
2091 size += in->HashEncryptionAlgorithm.Parameters.cbData;
2092 size += in->EncryptedHash.cbData;
2093 /* align pointer */
2094 size = ALIGN_DWORD_PTR(size);
2095 size += CRYPT_SizeOfAttributes(&in->AuthAttrs);
2096 size += CRYPT_SizeOfAttributes(&in->UnauthAttrs);
2097 if (!pvData)
2098 {
2099 *pcbData = size;
2100 ret = TRUE;
2101 }
2102 else if (*pcbData < size)
2103 {
2104 *pcbData = size;
2105 SetLastError(ERROR_MORE_DATA);
2106 ret = FALSE;
2107 }
2108 else
2109 {
2110 LPBYTE nextData = (BYTE *)pvData + sizeof(CMSG_SIGNER_INFO);
2111 CMSG_SIGNER_INFO *out = (CMSG_SIGNER_INFO *)pvData;
2112
2113 ret = TRUE;
2114 out->dwVersion = in->dwVersion;
2115 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2116 {
2117 CRYPT_CopyBlob(&out->Issuer,
2118 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData);
2119 CRYPT_CopyBlob(&out->SerialNumber,
2120 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData);
2121 }
2122 else
2123 ret = CRYPT_CopyKeyIdAsIssuerAndSerial(&out->Issuer, &out->SerialNumber,
2124 &in->SignerId.u.KeyId, rdnSize, &nextData);
2125 if (ret)
2126 {
2127 CRYPT_CopyAlgorithmId(&out->HashAlgorithm, &in->HashAlgorithm,
2128 &nextData);
2129 CRYPT_CopyAlgorithmId(&out->HashEncryptionAlgorithm,
2130 &in->HashEncryptionAlgorithm, &nextData);
2131 CRYPT_CopyBlob(&out->EncryptedHash, &in->EncryptedHash, &nextData);
2132 nextData = POINTER_ALIGN_DWORD_PTR(nextData);
2133 CRYPT_CopyAttributes(&out->AuthAttrs, &in->AuthAttrs, &nextData);
2134 CRYPT_CopyAttributes(&out->UnauthAttrs, &in->UnauthAttrs, &nextData);
2135 }
2136 }
2137 TRACE("returning %d\n", ret);
2138 return ret;
2139}
2140
2141static BOOL CRYPT_CopyCMSSignerInfo(void *pvData, DWORD *pcbData,
2142 const CMSG_CMS_SIGNER_INFO *in)
2143{
2144 DWORD size = sizeof(CMSG_CMS_SIGNER_INFO);
2145 BOOL ret;
2146
2147 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in);
2148
2149 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2150 {
2151 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData;
2152 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData;
2153 }
2154 else
2155 size += in->SignerId.u.KeyId.cbData;
2156 if (in->HashAlgorithm.pszObjId)
2157 size += strlen(in->HashAlgorithm.pszObjId) + 1;
2158 size += in->HashAlgorithm.Parameters.cbData;
2159 if (in->HashEncryptionAlgorithm.pszObjId)
2160 size += strlen(in->HashEncryptionAlgorithm.pszObjId) + 1;
2161 size += in->HashEncryptionAlgorithm.Parameters.cbData;
2162 size += in->EncryptedHash.cbData;
2163 /* align pointer */
2164 size = ALIGN_DWORD_PTR(size);
2165 size += CRYPT_SizeOfAttributes(&in->AuthAttrs);
2166 size += CRYPT_SizeOfAttributes(&in->UnauthAttrs);
2167 if (!pvData)
2168 {
2169 *pcbData = size;
2170 ret = TRUE;
2171 }
2172 else if (*pcbData < size)
2173 {
2174 *pcbData = size;
2175 SetLastError(ERROR_MORE_DATA);
2176 ret = FALSE;
2177 }
2178 else
2179 {
2180 LPBYTE nextData = (BYTE *)pvData + sizeof(CMSG_CMS_SIGNER_INFO);
2181 CMSG_CMS_SIGNER_INFO *out = (CMSG_CMS_SIGNER_INFO *)pvData;
2182
2183 out->dwVersion = in->dwVersion;
2184 out->SignerId.dwIdChoice = in->SignerId.dwIdChoice;
2185 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2186 {
2187 CRYPT_CopyBlob(&out->SignerId.u.IssuerSerialNumber.Issuer,
2188 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData);
2189 CRYPT_CopyBlob(&out->SignerId.u.IssuerSerialNumber.SerialNumber,
2190 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData);
2191 }
2192 else
2193 CRYPT_CopyBlob(&out->SignerId.u.KeyId, &in->SignerId.u.KeyId, &nextData);
2194 CRYPT_CopyAlgorithmId(&out->HashAlgorithm, &in->HashAlgorithm,
2195 &nextData);
2196 CRYPT_CopyAlgorithmId(&out->HashEncryptionAlgorithm,
2197 &in->HashEncryptionAlgorithm, &nextData);
2198 CRYPT_CopyBlob(&out->EncryptedHash, &in->EncryptedHash, &nextData);
2199 nextData = POINTER_ALIGN_DWORD_PTR(nextData);
2200 CRYPT_CopyAttributes(&out->AuthAttrs, &in->AuthAttrs, &nextData);
2201 CRYPT_CopyAttributes(&out->UnauthAttrs, &in->UnauthAttrs, &nextData);
2202 ret = TRUE;
2203 }
2204 TRACE("returning %d\n", ret);
2205 return ret;
2206}
2207
2208static BOOL CRYPT_CopySignerCertInfo(void *pvData, DWORD *pcbData,
2209 const CMSG_CMS_SIGNER_INFO *in)
2210{
2211 DWORD size = sizeof(CERT_INFO), rdnSize = 0;
2212 BOOL ret;
2213
2214 TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in);
2215
2216 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2217 {
2218 size += in->SignerId.u.IssuerSerialNumber.Issuer.cbData;
2219 size += in->SignerId.u.IssuerSerialNumber.SerialNumber.cbData;
2220 }
2221 else
2222 {
2223 rdnSize = CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in->SignerId.u.KeyId);
2224 size += rdnSize;
2225 }
2226 if (!pvData)
2227 {
2228 *pcbData = size;
2229 ret = TRUE;
2230 }
2231 else if (*pcbData < size)
2232 {
2233 *pcbData = size;
2234 SetLastError(ERROR_MORE_DATA);
2235 ret = FALSE;
2236 }
2237 else
2238 {
2239 LPBYTE nextData = (BYTE *)pvData + sizeof(CERT_INFO);
2240 CERT_INFO *out = (CERT_INFO *)pvData;
2241
2242 memset(out, 0, sizeof(CERT_INFO));
2243 if (in->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2244 {
2245 CRYPT_CopyBlob(&out->Issuer,
2246 &in->SignerId.u.IssuerSerialNumber.Issuer, &nextData);
2247 CRYPT_CopyBlob(&out->SerialNumber,
2248 &in->SignerId.u.IssuerSerialNumber.SerialNumber, &nextData);
2249 ret = TRUE;
2250 }
2251 else
2252 ret = CRYPT_CopyKeyIdAsIssuerAndSerial(&out->Issuer, &out->SerialNumber,
2253 &in->SignerId.u.KeyId, rdnSize, &nextData);
2254 }
2255 TRACE("returning %d\n", ret);
2256 return ret;
2257}
2258
2259static BOOL CDecodeSignedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType,
2260 DWORD dwIndex, void *pvData, DWORD *pcbData)
2261{
2262 BOOL ret = FALSE;
2263
2264 switch (dwParamType)
2265 {
2266 case CMSG_TYPE_PARAM:
2267 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type));
2268 break;
2269 case CMSG_CONTENT_PARAM:
2270 if (msg->u.signed_data.info)
2271 {
2272 if (!strcmp(msg->u.signed_data.info->content.pszObjId,
2273 szOID_RSA_data))
2274 {
2275 CRYPT_DATA_BLOB *blob;
2276 DWORD size;
2277
2278 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
2279 msg->u.signed_data.info->content.Content.pbData,
2280 msg->u.signed_data.info->content.Content.cbData,
2281 CRYPT_DECODE_ALLOC_FLAG, NULL, (LPBYTE)&blob, &size);
2282 if (ret)
2283 {
2284 ret = CRYPT_CopyParam(pvData, pcbData, blob->pbData,
2285 blob->cbData);
2286 LocalFree((HANDLE)blob);
2287 }
2288 }
2289 else
2290 ret = CRYPT_CopyParam(pvData, pcbData,
2291 msg->u.signed_data.info->content.Content.pbData,
2292 msg->u.signed_data.info->content.Content.cbData);
2293 }
2294 else
2295 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2296 break;
2297 case CMSG_INNER_CONTENT_TYPE_PARAM:
2298 if (msg->u.signed_data.info)
2299 ret = CRYPT_CopyParam(pvData, pcbData,
2300 msg->u.signed_data.info->content.pszObjId,
2301 strlen(msg->u.signed_data.info->content.pszObjId) + 1);
2302 else
2303 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2304 break;
2305 case CMSG_SIGNER_COUNT_PARAM:
2306 if (msg->u.signed_data.info)
2307 ret = CRYPT_CopyParam(pvData, pcbData,
2308 &msg->u.signed_data.info->cSignerInfo, sizeof(DWORD));
2309 else
2310 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2311 break;
2312 case CMSG_SIGNER_INFO_PARAM:
2313 if (msg->u.signed_data.info)
2314 {
2315 if (dwIndex >= msg->u.signed_data.info->cSignerInfo)
2316 SetLastError(CRYPT_E_INVALID_INDEX);
2317 else
2318 ret = CRYPT_CopySignerInfo(pvData, pcbData,
2319 &msg->u.signed_data.info->rgSignerInfo[dwIndex]);
2320 }
2321 else
2322 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2323 break;
2324 case CMSG_SIGNER_CERT_INFO_PARAM:
2325 if (msg->u.signed_data.info)
2326 {
2327 if (dwIndex >= msg->u.signed_data.info->cSignerInfo)
2328 SetLastError(CRYPT_E_INVALID_INDEX);
2329 else
2330 ret = CRYPT_CopySignerCertInfo(pvData, pcbData,
2331 &msg->u.signed_data.info->rgSignerInfo[dwIndex]);
2332 }
2333 else
2334 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2335 break;
2336 case CMSG_CERT_COUNT_PARAM:
2337 if (msg->u.signed_data.info)
2338 ret = CRYPT_CopyParam(pvData, pcbData,
2339 &msg->u.signed_data.info->cCertEncoded, sizeof(DWORD));
2340 else
2341 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2342 break;
2343 case CMSG_CERT_PARAM:
2344 if (msg->u.signed_data.info)
2345 {
2346 if (dwIndex >= msg->u.signed_data.info->cCertEncoded)
2347 SetLastError(CRYPT_E_INVALID_INDEX);
2348 else
2349 ret = CRYPT_CopyParam(pvData, pcbData,
2350 msg->u.signed_data.info->rgCertEncoded[dwIndex].pbData,
2351 msg->u.signed_data.info->rgCertEncoded[dwIndex].cbData);
2352 }
2353 else
2354 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2355 break;
2356 case CMSG_CRL_COUNT_PARAM:
2357 if (msg->u.signed_data.info)
2358 ret = CRYPT_CopyParam(pvData, pcbData,
2359 &msg->u.signed_data.info->cCrlEncoded, sizeof(DWORD));
2360 else
2361 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2362 break;
2363 case CMSG_CRL_PARAM:
2364 if (msg->u.signed_data.info)
2365 {
2366 if (dwIndex >= msg->u.signed_data.info->cCrlEncoded)
2367 SetLastError(CRYPT_E_INVALID_INDEX);
2368 else
2369 ret = CRYPT_CopyParam(pvData, pcbData,
2370 msg->u.signed_data.info->rgCrlEncoded[dwIndex].pbData,
2371 msg->u.signed_data.info->rgCrlEncoded[dwIndex].cbData);
2372 }
2373 else
2374 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2375 break;
2376 case CMSG_COMPUTED_HASH_PARAM:
2377 if (msg->u.signed_data.info)
2378 {
2379 if (dwIndex >= msg->u.signed_data.cSignerHandle)
2380 SetLastError(CRYPT_E_INVALID_INDEX);
2381 else
2382 ret = CryptGetHashParam(
2383 msg->u.signed_data.signerHandles[dwIndex].contentHash,
2384 HP_HASHVAL, pvData, pcbData, 0);
2385 }
2386 else
2387 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2388 break;
2389 case CMSG_ATTR_CERT_COUNT_PARAM:
2390 if (msg->u.signed_data.info)
2391 {
2392 DWORD attrCertCount = 0;
2393
2394 ret = CRYPT_CopyParam(pvData, pcbData,
2395 &attrCertCount, sizeof(DWORD));
2396 }
2397 else
2398 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2399 break;
2400 case CMSG_ATTR_CERT_PARAM:
2401 if (msg->u.signed_data.info)
2402 SetLastError(CRYPT_E_INVALID_INDEX);
2403 else
2404 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2405 break;
2406 case CMSG_CMS_SIGNER_INFO_PARAM:
2407 if (msg->u.signed_data.info)
2408 {
2409 if (dwIndex >= msg->u.signed_data.info->cSignerInfo)
2410 SetLastError(CRYPT_E_INVALID_INDEX);
2411 else
2412 ret = CRYPT_CopyCMSSignerInfo(pvData, pcbData,
2413 &msg->u.signed_data.info->rgSignerInfo[dwIndex]);
2414 }
2415 else
2416 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2417 break;
2418 default:
2419 FIXME("unimplemented for %d\n", dwParamType);
2420 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2421 }
2422 return ret;
2423}
2424
2425static BOOL CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
2426 DWORD dwIndex, void *pvData, DWORD *pcbData)
2427{
2428 CDecodeMsg *msg = (CDecodeMsg *)hCryptMsg;
2429 BOOL ret = FALSE;
2430
2431 switch (msg->type)
2432 {
2433 case CMSG_HASHED:
2434 ret = CDecodeHashMsg_GetParam(msg, dwParamType, dwIndex, pvData,
2435 pcbData);
2436 break;
2437 case CMSG_SIGNED:
2438 ret = CDecodeSignedMsg_GetParam(msg, dwParamType, dwIndex, pvData,
2439 pcbData);
2440 break;
2441 default:
2442 switch (dwParamType)
2443 {
2444 case CMSG_TYPE_PARAM:
2445 ret = CRYPT_CopyParam(pvData, pcbData, &msg->type,
2446 sizeof(msg->type));
2447 break;
2448 default:
2449 {
2450 CRYPT_DATA_BLOB blob;
2451
2452 ret = ContextPropertyList_FindProperty(msg->properties, dwParamType,
2453 &blob);
2454 if (ret)
2455 ret = CRYPT_CopyParam(pvData, pcbData, blob.pbData,
2456 blob.cbData);
2457 else
2458 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2459 }
2460 }
2461 }
2462 return ret;
2463}
2464
2465static BOOL CDecodeHashMsg_VerifyHash(CDecodeMsg *msg)
2466{
2467 BOOL ret;
2468 CRYPT_DATA_BLOB hashBlob;
2469
2470 ret = ContextPropertyList_FindProperty(msg->properties,
2471 CMSG_HASH_DATA_PARAM, &hashBlob);
2472 if (ret)
2473 {
2474 DWORD computedHashSize = 0;
2475
2476 ret = CDecodeHashMsg_GetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL,
2477 &computedHashSize);
2478 if (hashBlob.cbData == computedHashSize)
2479 {
2480 LPBYTE computedHash = CryptMemAlloc(computedHashSize);
2481
2482 if (computedHash)
2483 {
2484 ret = CDecodeHashMsg_GetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
2485 computedHash, &computedHashSize);
2486 if (ret)
2487 {
2488 if (memcmp(hashBlob.pbData, computedHash, hashBlob.cbData))
2489 {
2490 SetLastError(CRYPT_E_HASH_VALUE);
2491 ret = FALSE;
2492 }
2493 }
2494 CryptMemFree(computedHash);
2495 }
2496 else
2497 {
2498 SetLastError(ERROR_OUTOFMEMORY);
2499 ret = FALSE;
2500 }
2501 }
2502 else
2503 {
2504 SetLastError(CRYPT_E_HASH_VALUE);
2505 ret = FALSE;
2506 }
2507 }
2508 return ret;
2509}
2510
2511static BOOL CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg *msg,
2512 HCRYPTPROV prov, DWORD signerIndex, PCERT_PUBLIC_KEY_INFO keyInfo)
2513{
2514 HCRYPTKEY key;
2515 BOOL ret;
2516
2517 if (!prov)
2518 prov = msg->crypt_prov;
2519 ret = CryptImportPublicKeyInfo(prov, X509_ASN_ENCODING, keyInfo, &key);
2520 if (ret)
2521 {
2522 HCRYPTHASH hash;
2523 CRYPT_HASH_BLOB reversedHash;
2524
2525 if (msg->u.signed_data.info->rgSignerInfo[signerIndex].AuthAttrs.cAttr)
2526 hash = msg->u.signed_data.signerHandles[signerIndex].authAttrHash;
2527 else
2528 hash = msg->u.signed_data.signerHandles[signerIndex].contentHash;
2529 ret = CRYPT_ConstructBlob(&reversedHash,
2530 &msg->u.signed_data.info->rgSignerInfo[signerIndex].EncryptedHash);
2531 if (ret)
2532 {
2533 CRYPT_ReverseBytes(&reversedHash);
2534 ret = CryptVerifySignatureW(hash, reversedHash.pbData,
2535 reversedHash.cbData, key, NULL, 0);
2536 CryptMemFree(reversedHash.pbData);
2537 }
2538 CryptDestroyKey(key);
2539 }
2540 return ret;
2541}
2542
2543static BOOL CDecodeSignedMsg_VerifySignature(CDecodeMsg *msg, PCERT_INFO info)
2544{
2545 BOOL ret = FALSE;
2546 DWORD i;
2547
2548 if (!msg->u.signed_data.signerHandles)
2549 {
2550 SetLastError(NTE_BAD_SIGNATURE);
2551 return FALSE;
2552 }
2553 for (i = 0; !ret && i < msg->u.signed_data.info->cSignerInfo; i++)
2554 {
2555 PCMSG_CMS_SIGNER_INFO signerInfo =
2556 &msg->u.signed_data.info->rgSignerInfo[i];
2557
2558 if (signerInfo->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2559 {
2560 ret = CertCompareCertificateName(X509_ASN_ENCODING,
2561 &signerInfo->SignerId.u.IssuerSerialNumber.Issuer,
2562 &info->Issuer);
2563 if (ret)
2564 {
2565 ret = CertCompareIntegerBlob(
2566 &signerInfo->SignerId.u.IssuerSerialNumber.SerialNumber,
2567 &info->SerialNumber);
2568 if (ret)
2569 break;
2570 }
2571 }
2572 else
2573 {
2574 FIXME("signer %d: unimplemented for key id\n", i);
2575 }
2576 }
2577 if (ret)
2578 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, 0, i,
2579 &info->SubjectPublicKeyInfo);
2580 else
2581 SetLastError(CRYPT_E_SIGNER_NOT_FOUND);
2582
2583 return ret;
2584}
2585
2586static BOOL CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg *msg,
2587 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para)
2588{
2589 BOOL ret = FALSE;
2590
2591 if (para->cbSize != sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA))
2592 SetLastError(ERROR_INVALID_PARAMETER);
2593 else if (para->dwSignerIndex >= msg->u.signed_data.info->cSignerInfo)
2594 SetLastError(CRYPT_E_SIGNER_NOT_FOUND);
2595 else if (!msg->u.signed_data.signerHandles)
2596 SetLastError(NTE_BAD_SIGNATURE);
2597 else
2598 {
2599 switch (para->dwSignerType)
2600 {
2601 case CMSG_VERIFY_SIGNER_PUBKEY:
2602 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg,
2603 para->hCryptProv, para->dwSignerIndex,
2604 (PCERT_PUBLIC_KEY_INFO)para->pvSigner);
2605 break;
2606 case CMSG_VERIFY_SIGNER_CERT:
2607 {
2608 PCCERT_CONTEXT cert = (PCCERT_CONTEXT)para->pvSigner;
2609
2610 ret = CDecodeSignedMsg_VerifySignatureWithKey(msg, para->hCryptProv,
2611 para->dwSignerIndex, &cert->pCertInfo->SubjectPublicKeyInfo);
2612 break;
2613 }
2614 default:
2615 FIXME("unimplemented for signer type %d\n", para->dwSignerType);
2616 SetLastError(CRYPT_E_SIGNER_NOT_FOUND);
2617 }
2618 }
2619 return ret;
2620}
2621
2622static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags,
2623 DWORD dwCtrlType, const void *pvCtrlPara)
2624{
2625 CDecodeMsg *msg = (CDecodeMsg *)hCryptMsg;
2626 BOOL ret = FALSE;
2627
2628 switch (dwCtrlType)
2629 {
2630 case CMSG_CTRL_VERIFY_SIGNATURE:
2631 switch (msg->type)
2632 {
2633 case CMSG_SIGNED:
2634 ret = CDecodeSignedMsg_VerifySignature(msg, (PCERT_INFO)pvCtrlPara);
2635 break;
2636 default:
2637 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2638 }
2639 break;
2640 case CMSG_CTRL_DECRYPT:
2641 switch (msg->type)
2642 {
2643 default:
2644 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2645 }
2646 break;
2647 case CMSG_CTRL_VERIFY_HASH:
2648 switch (msg->type)
2649 {
2650 case CMSG_HASHED:
2651 ret = CDecodeHashMsg_VerifyHash(msg);
2652 break;
2653 default:
2654 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2655 }
2656 break;
2657 case CMSG_CTRL_VERIFY_SIGNATURE_EX:
2658 switch (msg->type)
2659 {
2660 case CMSG_SIGNED:
2661 ret = CDecodeSignedMsg_VerifySignatureEx(msg,
2662 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA)pvCtrlPara);
2663 break;
2664 default:
2665 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
2666 }
2667 break;
2668 default:
2669 SetLastError(CRYPT_E_CONTROL_TYPE);
2670 }
2671 return ret;
2672}
2673
2674HCRYPTMSG WINAPI CryptMsgOpenToDecode(DWORD dwMsgEncodingType, DWORD dwFlags,
2675 DWORD dwMsgType, HCRYPTPROV_LEGACY hCryptProv, PCERT_INFO pRecipientInfo,
2676 PCMSG_STREAM_INFO pStreamInfo)
2677{
2678 CDecodeMsg *msg;
2679
2680 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType,
2681 dwFlags, dwMsgType, hCryptProv, pRecipientInfo, pStreamInfo);
2682
2683 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING)
2684 {
2685 SetLastError(E_INVALIDARG);
2686 return NULL;
2687 }
2688 msg = CryptMemAlloc(sizeof(CDecodeMsg));
2689 if (msg)
2690 {
2691 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo,
2692 CDecodeMsg_Close, CDecodeMsg_GetParam, CDecodeMsg_Update,
2693 CDecodeMsg_Control);
2694 msg->type = dwMsgType;
2695 if (hCryptProv)
2696 msg->crypt_prov = hCryptProv;
2697 else
2698 {
2699 msg->crypt_prov = CRYPT_GetDefaultProvider();
2700 msg->base.open_flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
2701 }
2702 memset(&msg->u, 0, sizeof(msg->u));
2703 msg->msg_data.cbData = 0;
2704 msg->msg_data.pbData = NULL;
2705 msg->detached_data.cbData = 0;
2706 msg->detached_data.pbData = NULL;
2707 msg->properties = ContextPropertyList_Create();
2708 }
2709 return msg;
2710}
2711
2712HCRYPTMSG WINAPI CryptMsgDuplicate(HCRYPTMSG hCryptMsg)
2713{
2714 TRACE("(%p)\n", hCryptMsg);
2715
2716 if (hCryptMsg)
2717 {
2718 CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
2719
2720 InterlockedIncrement(&msg->ref);
2721 }
2722 return hCryptMsg;
2723}
2724
2725BOOL WINAPI CryptMsgClose(HCRYPTMSG hCryptMsg)
2726{
2727 TRACE("(%p)\n", hCryptMsg);
2728
2729 if (hCryptMsg)
2730 {
2731 CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
2732
2733 if (InterlockedDecrement(&msg->ref) == 0)
2734 {
2735 TRACE("freeing %p\n", msg);
2736 if (msg->close)
2737 msg->close(msg);
2738 CryptMemFree(msg);
2739 }
2740 }
2741 return TRUE;
2742}
2743
2744BOOL WINAPI CryptMsgUpdate(HCRYPTMSG hCryptMsg, const BYTE *pbData,
2745 DWORD cbData, BOOL fFinal)
2746{
2747 CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
2748
2749 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal);
2750
2751 return msg->update(hCryptMsg, pbData, cbData, fFinal);
2752}
2753
2754BOOL WINAPI CryptMsgGetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
2755 DWORD dwIndex, void *pvData, DWORD *pcbData)
2756{
2757 CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
2758
2759 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex,
2760 pvData, pcbData);
2761 return msg->get_param(hCryptMsg, dwParamType, dwIndex, pvData, pcbData);
2762}
2763
2764BOOL WINAPI CryptMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags,
2765 DWORD dwCtrlType, const void *pvCtrlPara)
2766{
2767 CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
2768
2769 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg, dwFlags, dwCtrlType,
2770 pvCtrlPara);
2771 return msg->control(hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara);
2772}
2773
2774static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg,
2775 DWORD dwSignerIndex)
2776{
2777 CERT_INFO *certInfo = NULL;
2778 DWORD size;
2779
2780 if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL,
2781 &size))
2782 {
2783 certInfo = CryptMemAlloc(size);
2784 if (certInfo)
2785 {
2786 if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM,
2787 dwSignerIndex, certInfo, &size))
2788 {
2789 CryptMemFree(certInfo);
2790 certInfo = NULL;
2791 }
2792 }
2793 }
2794 return certInfo;
2795}
2796
2797BOOL WINAPI CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg, DWORD cSignerStore,
2798 HCERTSTORE *rghSignerStore, DWORD dwFlags, PCCERT_CONTEXT *ppSigner,
2799 DWORD *pdwSignerIndex)
2800{
2801 HCERTSTORE store;
2802 DWORD i, signerIndex = 0;
2803 PCCERT_CONTEXT signerCert = NULL;
2804 BOOL ret = FALSE;
2805
2806 TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg, cSignerStore,
2807 rghSignerStore, dwFlags, ppSigner, pdwSignerIndex);
2808
2809 /* Clear output parameters */
2810 if (ppSigner)
2811 *ppSigner = NULL;
2812 if (pdwSignerIndex && !(dwFlags & CMSG_USE_SIGNER_INDEX_FLAG))
2813 *pdwSignerIndex = 0;
2814
2815 /* Create store to search for signer certificates */
2816 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
2817 CERT_STORE_CREATE_NEW_FLAG, NULL);
2818 if (!(dwFlags & CMSG_TRUSTED_SIGNER_FLAG))
2819 {
2820 HCERTSTORE msgStore = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0,
2821 hCryptMsg);
2822
2823 CertAddStoreToCollection(store, msgStore, 0, 0);
2824 CertCloseStore(msgStore, 0);
2825 }
2826 for (i = 0; i < cSignerStore; i++)
2827 CertAddStoreToCollection(store, rghSignerStore[i], 0, 0);
2828
2829 /* Find signer cert */
2830 if (dwFlags & CMSG_USE_SIGNER_INDEX_FLAG)
2831 {
2832 CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg,
2833 *pdwSignerIndex);
2834
2835 if (signer)
2836 {
2837 signerIndex = *pdwSignerIndex;
2838 signerCert = CertFindCertificateInStore(store, X509_ASN_ENCODING,
2839 0, CERT_FIND_SUBJECT_CERT, signer, NULL);
2840 CryptMemFree(signer);
2841 }
2842 }
2843 else
2844 {
2845 DWORD count, size = sizeof(count);
2846
2847 if (CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_COUNT_PARAM, 0, &count,
2848 &size))
2849 {
2850 for (i = 0; !signerCert && i < count; i++)
2851 {
2852 CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg,
2853 i);
2854
2855 if (signer)
2856 {
2857 signerCert = CertFindCertificateInStore(store,
2858 X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, signer,
2859 NULL);
2860 if (signerCert)
2861 signerIndex = i;
2862 CryptMemFree(signer);
2863 }
2864 }
2865 }
2866 if (!signerCert)
2867 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER);
2868 }
2869 if (signerCert)
2870 {
2871 if (!(dwFlags & CMSG_SIGNER_ONLY_FLAG))
2872 ret = CryptMsgControl(hCryptMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE,
2873 signerCert->pCertInfo);
2874 else
2875 ret = TRUE;
2876 if (ret)
2877 {
2878 if (ppSigner)
2879 *ppSigner = CertDuplicateCertificateContext(signerCert);
2880 if (pdwSignerIndex)
2881 *pdwSignerIndex = signerIndex;
2882 }
2883 CertFreeCertificateContext(signerCert);
2884 }
2885
2886 CertCloseStore(store, 0);
2887 return ret;
2888}
2889
2890BOOL WINAPI CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv,
2891 DWORD dwEncodingType, PBYTE pbSignerInfo, DWORD cbSignerInfo,
2892 PBYTE pbSignerInfoCountersignature, DWORD cbSignerInfoCountersignature,
2893 DWORD dwSignerType, void *pvSigner, DWORD dwFlags, void *pvReserved)
2894{
2895 FIXME("(%08lx, %08x, %p, %d, %p, %d, %d, %p, %08x, %p): stub\n", hCryptProv,
2896 dwEncodingType, pbSignerInfo, cbSignerInfo, pbSignerInfoCountersignature,
2897 cbSignerInfoCountersignature, dwSignerType, pvSigner, dwFlags, pvReserved);
2898 return FALSE;
2899}
Note: See TracBrowser for help on using the repository browser.