2 * Copyright 2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/port.h"
23 #define NONAMELESSUNION
29 #include "wine/debug.h"
30 #include "wine/exception.h"
31 #include "crypt32_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
35 /* Called when a message's ref count reaches zero. Free any message-specific
38 typedef void (*CryptMsgCloseFunc
)(HCRYPTMSG msg
);
40 typedef BOOL (*CryptMsgGetParamFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
41 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
);
43 typedef BOOL (*CryptMsgUpdateFunc
)(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
44 DWORD cbData
, BOOL fFinal
);
46 typedef BOOL (*CryptMsgControlFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
47 DWORD dwCtrlType
, const void *pvCtrlPara
);
49 static BOOL
CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
50 DWORD dwCtrlType
, const void *pvCtrlPara
)
52 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
53 SetLastError(E_INVALIDARG
);
57 typedef enum _CryptMsgState
{
60 MsgStateDataFinalized
,
64 typedef struct _CryptMsgBase
69 CMSG_STREAM_INFO stream_info
;
71 CryptMsgCloseFunc close
;
72 CryptMsgUpdateFunc update
;
73 CryptMsgGetParamFunc get_param
;
74 CryptMsgControlFunc control
;
77 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
78 PCMSG_STREAM_INFO pStreamInfo
, CryptMsgCloseFunc close
,
79 CryptMsgGetParamFunc get_param
, CryptMsgUpdateFunc update
,
80 CryptMsgControlFunc control
)
83 msg
->open_flags
= dwFlags
;
87 msg
->stream_info
= *pStreamInfo
;
91 msg
->streamed
= FALSE
;
92 memset(&msg
->stream_info
, 0, sizeof(msg
->stream_info
));
95 msg
->get_param
= get_param
;
97 msg
->control
= control
;
98 msg
->state
= MsgStateInit
;
101 typedef struct _CDataEncodeMsg
104 DWORD bare_content_len
;
108 static const BYTE empty_data_content
[] = { 0x04,0x00 };
110 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
112 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
114 if (msg
->bare_content
!= empty_data_content
)
115 LocalFree(msg
->bare_content
);
118 static BOOL WINAPI
CRYPT_EncodeContentLength(DWORD dwCertEncodingType
,
119 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
120 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
122 DWORD dataLen
= *(DWORD
*)pvStructInfo
;
126 /* Trick: report bytes needed based on total message length, even though
127 * the message isn't available yet. The caller will use the length
128 * reported here to encode its length.
130 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
132 *pcbEncoded
= 1 + lenBytes
+ dataLen
;
135 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
136 pcbEncoded
, 1 + lenBytes
)))
138 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
139 pbEncoded
= *(BYTE
**)pbEncoded
;
140 *pbEncoded
++ = ASN_OCTETSTRING
;
141 CRYPT_EncodeLen(dataLen
, pbEncoded
,
148 static BOOL
CRYPT_EncodeDataContentInfoHeader(CDataEncodeMsg
*msg
,
149 CRYPT_DATA_BLOB
*header
)
153 if (msg
->base
.streamed
&& msg
->base
.stream_info
.cbContent
== 0xffffffff)
155 static const BYTE headerValue
[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
156 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
158 header
->pbData
= LocalAlloc(0, sizeof(headerValue
));
161 header
->cbData
= sizeof(headerValue
);
162 memcpy(header
->pbData
, headerValue
, sizeof(headerValue
));
170 struct AsnConstructedItem constructed
= { 0,
171 &msg
->base
.stream_info
.cbContent
, CRYPT_EncodeContentLength
};
172 struct AsnEncodeSequenceItem items
[2] = {
173 { szOID_RSA_data
, CRYPT_AsnEncodeOid
, 0 },
174 { &constructed
, CRYPT_AsnEncodeConstructed
, 0 },
177 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
178 sizeof(items
) / sizeof(items
[0]), CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
179 (LPBYTE
)&header
->pbData
, &header
->cbData
);
182 /* Trick: subtract the content length from the reported length,
183 * as the actual content hasn't come yet.
185 header
->cbData
-= msg
->base
.stream_info
.cbContent
;
191 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
192 DWORD cbData
, BOOL fFinal
)
194 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
197 if (msg
->base
.state
== MsgStateFinalized
)
198 SetLastError(CRYPT_E_MSG_ERROR
);
199 else if (msg
->base
.streamed
)
203 if (msg
->base
.state
!= MsgStateUpdated
)
205 CRYPT_DATA_BLOB header
;
207 ret
= CRYPT_EncodeDataContentInfoHeader(msg
, &header
);
210 ret
= msg
->base
.stream_info
.pfnStreamOutput(
211 msg
->base
.stream_info
.pvArg
, header
.pbData
, header
.cbData
,
213 LocalFree(header
.pbData
);
216 /* Curiously, every indefinite-length streamed update appears to
217 * get its own tag and length, regardless of fFinal.
219 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
224 ret
= CRYPT_EncodeContentLength(X509_ASN_ENCODING
, NULL
,
225 &cbData
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (BYTE
*)&header
,
229 ret
= msg
->base
.stream_info
.pfnStreamOutput(
230 msg
->base
.stream_info
.pvArg
, header
, headerLen
,
237 ret
= msg
->base
.stream_info
.pfnStreamOutput(
238 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
240 msg
->base
.state
= MsgStateUpdated
;
244 msg
->base
.state
= MsgStateFinalized
;
245 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
247 BYTE indefinite_trailer
[6] = { 0 };
249 ret
= msg
->base
.stream_info
.pfnStreamOutput(
250 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
253 ret
= msg
->base
.stream_info
.pfnStreamOutput(
254 msg
->base
.stream_info
.pvArg
, indefinite_trailer
,
255 sizeof(indefinite_trailer
), TRUE
);
258 ret
= msg
->base
.stream_info
.pfnStreamOutput(
259 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
, TRUE
);
264 SetLastError(STATUS_ACCESS_VIOLATION
);
273 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
274 SetLastError(E_INVALIDARG
);
276 SetLastError(CRYPT_E_MSG_ERROR
);
280 msg
->base
.state
= MsgStateFinalized
;
282 SetLastError(E_INVALIDARG
);
285 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
287 /* non-streamed data messages don't allow non-final updates,
288 * don't bother checking whether data already exist, they can't.
290 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
291 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
292 &msg
->bare_content_len
);
299 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
306 else if (*pcbData
< len
)
309 SetLastError(ERROR_MORE_DATA
);
315 memcpy(pvData
, src
, len
);
320 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
321 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
323 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
328 case CMSG_CONTENT_PARAM
:
329 if (msg
->base
.streamed
)
330 SetLastError(E_INVALIDARG
);
333 CRYPT_CONTENT_INFO info
;
334 char rsa_data
[] = "1.2.840.113549.1.7.1";
336 info
.pszObjId
= rsa_data
;
337 info
.Content
.cbData
= msg
->bare_content_len
;
338 info
.Content
.pbData
= msg
->bare_content
;
339 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
343 case CMSG_BARE_CONTENT_PARAM
:
344 if (msg
->base
.streamed
)
345 SetLastError(E_INVALIDARG
);
347 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->bare_content
,
348 msg
->bare_content_len
);
351 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
356 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
357 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
363 SetLastError(E_INVALIDARG
);
366 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
369 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
370 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
,
371 CRYPT_DefaultMsgControl
);
372 msg
->bare_content_len
= sizeof(empty_data_content
);
373 msg
->bare_content
= (LPBYTE
)empty_data_content
;
375 return (HCRYPTMSG
)msg
;
378 typedef struct _CHashEncodeMsg
383 CRYPT_DATA_BLOB data
;
386 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
388 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
390 CryptMemFree(msg
->data
.pbData
);
391 CryptDestroyHash(msg
->hash
);
392 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
393 CryptReleaseContext(msg
->prov
, 0);
396 static BOOL
CRYPT_EncodePKCSDigestedData(CHashEncodeMsg
*msg
, void *pvData
,
401 DWORD size
= sizeof(algID
);
403 ret
= CryptGetHashParam(msg
->hash
, HP_ALGID
, (BYTE
*)&algID
, &size
, 0);
406 CRYPT_DIGESTED_DATA digestedData
= { 0 };
407 char oid_rsa_data
[] = szOID_RSA_data
;
409 digestedData
.version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
410 digestedData
.DigestAlgorithm
.pszObjId
= (LPSTR
)CertAlgIdToOID(algID
);
411 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
412 /* Quirk: OID is only encoded messages if an update has happened */
413 if (msg
->base
.state
!= MsgStateInit
)
414 digestedData
.ContentInfo
.pszObjId
= oid_rsa_data
;
415 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->data
.cbData
)
417 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &msg
->data
,
418 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
419 (LPBYTE
)&digestedData
.ContentInfo
.Content
.pbData
,
420 &digestedData
.ContentInfo
.Content
.cbData
);
422 if (msg
->base
.state
== MsgStateFinalized
)
424 size
= sizeof(DWORD
);
425 ret
= CryptGetHashParam(msg
->hash
, HP_HASHSIZE
,
426 (LPBYTE
)&digestedData
.hash
.cbData
, &size
, 0);
429 digestedData
.hash
.pbData
= CryptMemAlloc(
430 digestedData
.hash
.cbData
);
431 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
,
432 digestedData
.hash
.pbData
, &digestedData
.hash
.cbData
, 0);
436 ret
= CRYPT_AsnEncodePKCSDigestedData(&digestedData
, pvData
,
438 CryptMemFree(digestedData
.hash
.pbData
);
439 LocalFree(digestedData
.ContentInfo
.Content
.pbData
);
444 static BOOL
CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
445 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
447 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
450 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
455 case CMSG_BARE_CONTENT_PARAM
:
456 if (msg
->base
.streamed
)
457 SetLastError(E_INVALIDARG
);
459 ret
= CRYPT_EncodePKCSDigestedData(msg
, pvData
, pcbData
);
461 case CMSG_CONTENT_PARAM
:
463 CRYPT_CONTENT_INFO info
;
465 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
466 &info
.Content
.cbData
);
469 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
470 if (info
.Content
.pbData
)
472 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
473 info
.Content
.pbData
, &info
.Content
.cbData
);
476 char oid_rsa_hashed
[] = szOID_RSA_hashedData
;
478 info
.pszObjId
= oid_rsa_hashed
;
479 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
480 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
482 CryptMemFree(info
.Content
.pbData
);
489 case CMSG_COMPUTED_HASH_PARAM
:
490 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
, (BYTE
*)pvData
, pcbData
,
493 case CMSG_VERSION_PARAM
:
494 if (msg
->base
.state
!= MsgStateFinalized
)
495 SetLastError(CRYPT_E_MSG_ERROR
);
498 DWORD version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
500 /* Since the data are always encoded as octets, the version is
501 * always 0 (see rfc3852, section 7)
503 ret
= CRYPT_CopyParam(pvData
, pcbData
, &version
, sizeof(version
));
507 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
512 static BOOL
CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
513 DWORD cbData
, BOOL fFinal
)
515 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
518 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
520 if (msg
->base
.state
== MsgStateFinalized
)
521 SetLastError(CRYPT_E_MSG_ERROR
);
522 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
524 /* Doesn't do much, as stream output is never called, and you
525 * can't get the content.
527 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
528 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
533 SetLastError(CRYPT_E_MSG_ERROR
);
536 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
539 msg
->data
.pbData
= CryptMemAlloc(cbData
);
540 if (msg
->data
.pbData
)
542 memcpy(msg
->data
.pbData
+ msg
->data
.cbData
, pbData
, cbData
);
543 msg
->data
.cbData
+= cbData
;
548 msg
->base
.state
= MsgStateFinalized
;
554 static HCRYPTMSG
CHashEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
555 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
558 const CMSG_HASHED_ENCODE_INFO
*info
=
559 (const CMSG_HASHED_ENCODE_INFO
*)pvMsgEncodeInfo
;
563 if (info
->cbSize
!= sizeof(CMSG_HASHED_ENCODE_INFO
))
565 SetLastError(E_INVALIDARG
);
568 if (!(algID
= CertOIDToAlgId(info
->HashAlgorithm
.pszObjId
)))
570 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
573 if (info
->hCryptProv
)
574 prov
= info
->hCryptProv
;
577 prov
= CRYPT_GetDefaultProvider();
578 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
580 msg
= CryptMemAlloc(sizeof(CHashEncodeMsg
));
583 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
584 CHashEncodeMsg_Close
, CHashEncodeMsg_GetParam
, CHashEncodeMsg_Update
,
585 CRYPT_DefaultMsgControl
);
587 msg
->data
.cbData
= 0;
588 msg
->data
.pbData
= NULL
;
589 if (!CryptCreateHash(prov
, algID
, 0, 0, &msg
->hash
))
595 return (HCRYPTMSG
)msg
;
598 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
601 PCERT_INFO pCertInfo
;
602 HCRYPTPROV hCryptProv
;
604 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm
;
607 PCRYPT_ATTRIBUTE rgAuthAttr
;
609 PCRYPT_ATTRIBUTE rgUnauthAttr
;
611 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm
;
612 void *pvHashEncryptionAuxInfo
;
613 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS
;
615 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
619 PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners
;
621 PCERT_BLOB rgCertEncoded
;
623 PCRL_BLOB rgCrlEncoded
;
624 DWORD cAttrCertEncoded
;
625 PCERT_BLOB rgAttrCertEncoded
;
626 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS
;
628 static BOOL
CRYPT_IsValidSigner(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*signer
)
630 if (signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO
) &&
631 signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
633 SetLastError(E_INVALIDARG
);
636 if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
638 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
640 SetLastError(E_INVALIDARG
);
643 if (!signer
->pCertInfo
->Issuer
.cbData
)
645 SetLastError(E_INVALIDARG
);
649 else if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
651 switch (signer
->SignerId
.dwIdChoice
)
654 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
656 SetLastError(E_INVALIDARG
);
659 if (!signer
->pCertInfo
->Issuer
.cbData
)
661 SetLastError(E_INVALIDARG
);
665 case CERT_ID_ISSUER_SERIAL_NUMBER
:
666 if (!signer
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
)
668 SetLastError(E_INVALIDARG
);
671 if (!signer
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
673 SetLastError(E_INVALIDARG
);
677 case CERT_ID_KEY_IDENTIFIER
:
678 if (!signer
->SignerId
.u
.KeyId
.cbData
)
680 SetLastError(E_INVALIDARG
);
685 SetLastError(E_INVALIDARG
);
687 if (signer
->HashEncryptionAlgorithm
.pszObjId
)
689 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
693 if (!signer
->hCryptProv
)
695 SetLastError(E_INVALIDARG
);
698 if (!CertOIDToAlgId(signer
->HashAlgorithm
.pszObjId
))
700 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
706 static BOOL
CRYPT_ConstructBlob(CRYPT_DATA_BLOB
*out
, const CRYPT_DATA_BLOB
*in
)
710 out
->cbData
= in
->cbData
;
713 out
->pbData
= CryptMemAlloc(out
->cbData
);
715 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
724 typedef struct _BlobArray
727 PCRYPT_DATA_BLOB blobs
;
730 static BOOL
CRYPT_ConstructBlobArray(BlobArray
*out
, const BlobArray
*in
)
734 out
->cBlobs
= in
->cBlobs
;
737 out
->blobs
= CryptMemAlloc(out
->cBlobs
* sizeof(CRYPT_DATA_BLOB
));
742 memset(out
->blobs
, 0, out
->cBlobs
* sizeof(CRYPT_DATA_BLOB
));
743 for (i
= 0; ret
&& i
< out
->cBlobs
; i
++)
744 ret
= CRYPT_ConstructBlob(&out
->blobs
[i
], &in
->blobs
[i
]);
752 static void CRYPT_FreeBlobArray(BlobArray
*array
)
756 for (i
= 0; i
< array
->cBlobs
; i
++)
757 CryptMemFree(array
->blobs
[i
].pbData
);
758 CryptMemFree(array
->blobs
);
761 static BOOL
CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE
*out
,
762 const CRYPT_ATTRIBUTE
*in
)
766 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
769 strcpy(out
->pszObjId
, in
->pszObjId
);
770 ret
= CRYPT_ConstructBlobArray((BlobArray
*)&out
->cValue
,
771 (const BlobArray
*)&in
->cValue
);
778 static BOOL
CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES
*out
,
779 const CRYPT_ATTRIBUTES
*in
)
783 out
->cAttr
= in
->cAttr
;
786 out
->rgAttr
= CryptMemAlloc(out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
791 memset(out
->rgAttr
, 0, out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
792 for (i
= 0; ret
&& i
< out
->cAttr
; i
++)
793 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[i
], &in
->rgAttr
[i
]);
803 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
804 static BOOL
CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO
*info
,
805 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*in
)
809 if (in
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
811 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
812 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
813 &in
->pCertInfo
->Issuer
);
815 ret
= CRYPT_ConstructBlob(
816 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
817 &in
->pCertInfo
->SerialNumber
);
818 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
822 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS).
823 * See CRYPT_IsValidSigner.
825 if (!in
->SignerId
.dwIdChoice
)
827 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
828 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
829 &in
->pCertInfo
->Issuer
);
831 ret
= CRYPT_ConstructBlob(
832 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
833 &in
->pCertInfo
->SerialNumber
);
834 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
836 else if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
838 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
839 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
840 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
841 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
);
843 ret
= CRYPT_ConstructBlob(
844 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
845 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
);
849 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */
850 info
->dwVersion
= CMSG_SIGNER_INFO_V3
;
851 info
->SignerId
.dwIdChoice
= CERT_ID_KEY_IDENTIFIER
;
852 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.KeyId
,
853 &in
->SignerId
.u
.KeyId
);
856 /* Assumption: algorithm IDs will point to static strings, not
857 * stack-based ones, so copying the pointer values is safe.
859 info
->HashAlgorithm
.pszObjId
= in
->HashAlgorithm
.pszObjId
;
861 ret
= CRYPT_ConstructBlob(&info
->HashAlgorithm
.Parameters
,
862 &in
->HashAlgorithm
.Parameters
);
863 memset(&info
->HashEncryptionAlgorithm
, 0,
864 sizeof(info
->HashEncryptionAlgorithm
));
866 ret
= CRYPT_ConstructAttributes(&info
->AuthAttrs
,
867 (CRYPT_ATTRIBUTES
*)&in
->cAuthAttr
);
869 ret
= CRYPT_ConstructAttributes(&info
->UnauthAttrs
,
870 (CRYPT_ATTRIBUTES
*)&in
->cUnauthAttr
);
874 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO
*info
)
878 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
880 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
881 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
884 CryptMemFree(info
->SignerId
.u
.KeyId
.pbData
);
885 CryptMemFree(info
->HashAlgorithm
.Parameters
.pbData
);
886 CryptMemFree(info
->EncryptedHash
.pbData
);
887 for (i
= 0; i
< info
->AuthAttrs
.cAttr
; i
++)
889 for (j
= 0; j
< info
->AuthAttrs
.rgAttr
[i
].cValue
; j
++)
890 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
891 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
);
892 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].pszObjId
);
894 CryptMemFree(info
->AuthAttrs
.rgAttr
);
895 for (i
= 0; i
< info
->UnauthAttrs
.cAttr
; i
++)
897 for (j
= 0; j
< info
->UnauthAttrs
.rgAttr
[i
].cValue
; j
++)
898 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
899 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
);
900 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].pszObjId
);
902 CryptMemFree(info
->UnauthAttrs
.rgAttr
);
905 typedef struct _CSignerHandles
907 HCRYPTHASH contentHash
;
908 HCRYPTHASH authAttrHash
;
911 typedef struct _CSignedMsgData
913 CRYPT_SIGNED_INFO
*info
;
915 CSignerHandles
*signerHandles
;
918 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
919 * Assumes signerIndex is a valid idnex, and that msg_data's info has already
922 static BOOL
CSignedMsgData_ConstructSignerHandles(CSignedMsgData
*msg_data
,
923 DWORD signerIndex
, HCRYPTPROV crypt_prov
)
928 algID
= CertOIDToAlgId(
929 msg_data
->info
->rgSignerInfo
[signerIndex
].HashAlgorithm
.pszObjId
);
930 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
931 &msg_data
->signerHandles
->contentHash
);
932 if (ret
&& msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
> 0)
933 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
934 &msg_data
->signerHandles
->authAttrHash
);
938 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
941 static BOOL
CSignedMsgData_AllocateHandles(CSignedMsgData
*msg_data
)
945 if (msg_data
->info
->cSignerInfo
)
947 msg_data
->signerHandles
=
948 CryptMemAlloc(msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
949 if (msg_data
->signerHandles
)
951 msg_data
->cSignerHandle
= msg_data
->info
->cSignerInfo
;
952 memset(msg_data
->signerHandles
, 0,
953 msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
957 msg_data
->cSignerHandle
= 0;
963 msg_data
->cSignerHandle
= 0;
964 msg_data
->signerHandles
= NULL
;
969 static void CSignedMsgData_CloseHandles(CSignedMsgData
*msg_data
)
973 for (i
= 0; i
< msg_data
->cSignerHandle
; i
++)
975 if (msg_data
->signerHandles
[i
].contentHash
)
976 CryptDestroyHash(msg_data
->signerHandles
[i
].contentHash
);
977 if (msg_data
->signerHandles
[i
].authAttrHash
)
978 CryptDestroyHash(msg_data
->signerHandles
[i
].authAttrHash
);
980 CryptMemFree(msg_data
->signerHandles
);
981 msg_data
->signerHandles
= NULL
;
982 msg_data
->cSignerHandle
= 0;
985 static BOOL
CSignedMsgData_UpdateHash(CSignedMsgData
*msg_data
,
986 const BYTE
*pbData
, DWORD cbData
)
991 for (i
= 0; ret
&& i
< msg_data
->cSignerHandle
; i
++)
992 ret
= CryptHashData(msg_data
->signerHandles
[i
].contentHash
, pbData
,
997 static BOOL
CRYPT_AppendAttribute(CRYPT_ATTRIBUTES
*out
,
998 const CRYPT_ATTRIBUTE
*in
)
1002 out
->rgAttr
= CryptMemRealloc(out
->rgAttr
,
1003 (out
->cAttr
+ 1) * sizeof(CRYPT_ATTRIBUTE
));
1006 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[out
->cAttr
], in
);
1013 static BOOL
CSignedMsgData_AppendMessageDigestAttribute(
1014 CSignedMsgData
*msg_data
, DWORD signerIndex
)
1018 CRYPT_HASH_BLOB hash
= { 0, NULL
}, encodedHash
= { 0, NULL
};
1019 char messageDigest
[] = szOID_RSA_messageDigest
;
1020 CRYPT_ATTRIBUTE messageDigestAttr
= { messageDigest
, 1, &encodedHash
};
1022 size
= sizeof(DWORD
);
1023 ret
= CryptGetHashParam(
1024 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHSIZE
,
1025 (LPBYTE
)&hash
.cbData
, &size
, 0);
1028 hash
.pbData
= CryptMemAlloc(hash
.cbData
);
1029 ret
= CryptGetHashParam(
1030 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHVAL
,
1031 hash
.pbData
, &hash
.cbData
, 0);
1034 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &hash
, CRYPT_ENCODE_ALLOC_FLAG
,
1035 NULL
, (LPBYTE
)&encodedHash
.pbData
, &encodedHash
.cbData
);
1038 ret
= CRYPT_AppendAttribute(
1039 &msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
,
1040 &messageDigestAttr
);
1041 LocalFree(encodedHash
.pbData
);
1044 CryptMemFree(hash
.pbData
);
1054 static BOOL
CSignedMsgData_UpdateAuthenticatedAttributes(
1055 CSignedMsgData
*msg_data
, SignOrVerify flag
)
1060 TRACE("(%p)\n", msg_data
);
1062 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1064 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1068 BYTE oid_rsa_data_encoded
[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
1069 0xf7,0x0d,0x01,0x07,0x01 };
1070 CRYPT_DATA_BLOB content
= { sizeof(oid_rsa_data_encoded
),
1071 oid_rsa_data_encoded
};
1072 char contentType
[] = szOID_RSA_contentType
;
1073 CRYPT_ATTRIBUTE contentTypeAttr
= { contentType
, 1, &content
};
1075 /* FIXME: does this depend on inner OID? */
1076 ret
= CRYPT_AppendAttribute(
1077 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
, &contentTypeAttr
);
1079 ret
= CSignedMsgData_AppendMessageDigestAttribute(msg_data
,
1084 LPBYTE encodedAttrs
;
1087 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, PKCS_ATTRIBUTES
,
1088 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
,
1089 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&encodedAttrs
, &size
);
1092 ret
= CryptHashData(
1093 msg_data
->signerHandles
[i
].authAttrHash
, encodedAttrs
,
1095 LocalFree(encodedAttrs
);
1100 TRACE("returning %d\n", ret
);
1104 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB
*hash
)
1109 for (i
= 0; i
< hash
->cbData
/ 2; i
++)
1111 tmp
= hash
->pbData
[hash
->cbData
- i
- 1];
1112 hash
->pbData
[hash
->cbData
- i
- 1] = hash
->pbData
[i
];
1113 hash
->pbData
[i
] = tmp
;
1117 static BOOL
CSignedMsgData_Sign(CSignedMsgData
*msg_data
)
1122 TRACE("(%p)\n", msg_data
);
1124 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1128 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1129 hash
= msg_data
->signerHandles
[i
].authAttrHash
;
1131 hash
= msg_data
->signerHandles
[i
].contentHash
;
1132 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0, NULL
,
1133 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1136 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
=
1138 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1139 if (msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
)
1141 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0,
1142 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
,
1143 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1146 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
);
1155 static BOOL
CSignedMsgData_Update(CSignedMsgData
*msg_data
,
1156 const BYTE
*pbData
, DWORD cbData
, BOOL fFinal
, SignOrVerify flag
)
1158 BOOL ret
= CSignedMsgData_UpdateHash(msg_data
, pbData
, cbData
);
1162 ret
= CSignedMsgData_UpdateAuthenticatedAttributes(msg_data
, flag
);
1163 if (ret
&& flag
== Sign
)
1164 ret
= CSignedMsgData_Sign(msg_data
);
1169 typedef struct _CSignedEncodeMsg
1172 CRYPT_DATA_BLOB data
;
1173 CSignedMsgData msg_data
;
1176 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1178 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1181 CryptMemFree(msg
->data
.pbData
);
1182 CRYPT_FreeBlobArray((BlobArray
*)&msg
->msg_data
.info
->cCertEncoded
);
1183 CRYPT_FreeBlobArray((BlobArray
*)&msg
->msg_data
.info
->cCrlEncoded
);
1184 for (i
= 0; i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1185 CSignerInfo_Free(&msg
->msg_data
.info
->rgSignerInfo
[i
]);
1186 CSignedMsgData_CloseHandles(&msg
->msg_data
);
1187 CryptMemFree(msg
->msg_data
.info
->rgSignerInfo
);
1188 CryptMemFree(msg
->msg_data
.info
);
1191 static BOOL
CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1192 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1194 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1197 switch (dwParamType
)
1199 case CMSG_CONTENT_PARAM
:
1201 CRYPT_CONTENT_INFO info
;
1203 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1204 &info
.Content
.cbData
);
1207 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1208 if (info
.Content
.pbData
)
1210 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1211 info
.Content
.pbData
, &info
.Content
.cbData
);
1214 char oid_rsa_signed
[] = szOID_RSA_signedData
;
1216 info
.pszObjId
= oid_rsa_signed
;
1217 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1218 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1220 CryptMemFree(info
.Content
.pbData
);
1227 case CMSG_BARE_CONTENT_PARAM
:
1229 CRYPT_SIGNED_INFO info
;
1230 char oid_rsa_data
[] = szOID_RSA_data
;
1232 info
= *msg
->msg_data
.info
;
1233 /* Quirk: OID is only encoded messages if an update has happened */
1234 if (msg
->base
.state
!= MsgStateInit
)
1235 info
.content
.pszObjId
= oid_rsa_data
;
1237 info
.content
.pszObjId
= NULL
;
1238 if (msg
->data
.cbData
)
1240 CRYPT_DATA_BLOB blob
= { msg
->data
.cbData
, msg
->data
.pbData
};
1242 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1243 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
1244 &info
.content
.Content
.pbData
, &info
.content
.Content
.cbData
);
1248 info
.content
.Content
.cbData
= 0;
1249 info
.content
.Content
.pbData
= NULL
;
1254 ret
= CRYPT_AsnEncodeCMSSignedInfo(&info
, pvData
, pcbData
);
1255 LocalFree(info
.content
.Content
.pbData
);
1259 case CMSG_COMPUTED_HASH_PARAM
:
1260 if (dwIndex
>= msg
->msg_data
.cSignerHandle
)
1261 SetLastError(CRYPT_E_INVALID_INDEX
);
1263 ret
= CryptGetHashParam(
1264 msg
->msg_data
.signerHandles
[dwIndex
].contentHash
, HP_HASHVAL
,
1265 pvData
, pcbData
, 0);
1267 case CMSG_ENCODED_SIGNER
:
1268 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1269 SetLastError(CRYPT_E_INVALID_INDEX
);
1271 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1272 CMS_SIGNER_INFO
, &msg
->msg_data
.info
->rgSignerInfo
[dwIndex
], 0,
1273 NULL
, pvData
, pcbData
);
1275 case CMSG_VERSION_PARAM
:
1276 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->msg_data
.info
->version
,
1277 sizeof(msg
->msg_data
.info
->version
));
1280 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1285 static BOOL
CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1286 DWORD cbData
, BOOL fFinal
)
1288 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1291 if (msg
->base
.state
== MsgStateFinalized
)
1292 SetLastError(CRYPT_E_MSG_ERROR
);
1293 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1295 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
, fFinal
,
1297 if (msg
->base
.streamed
)
1298 FIXME("streamed partial stub\n");
1299 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1304 SetLastError(CRYPT_E_MSG_ERROR
);
1309 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1310 if (msg
->data
.pbData
)
1312 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1313 msg
->data
.cbData
= cbData
;
1320 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
,
1322 msg
->base
.state
= MsgStateFinalized
;
1328 static HCRYPTMSG
CSignedEncodeMsg_Open(DWORD dwFlags
,
1329 const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
1330 PCMSG_STREAM_INFO pStreamInfo
)
1332 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*info
=
1333 (const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*)pvMsgEncodeInfo
;
1335 CSignedEncodeMsg
*msg
;
1337 if (info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO
) &&
1338 info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1340 SetLastError(E_INVALIDARG
);
1343 if (info
->cbSize
== sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
) &&
1344 info
->cAttrCertEncoded
)
1346 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1349 for (i
= 0; i
< info
->cSigners
; i
++)
1350 if (!CRYPT_IsValidSigner(&info
->rgSigners
[i
]))
1352 msg
= CryptMemAlloc(sizeof(CSignedEncodeMsg
));
1357 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1358 CSignedEncodeMsg_Close
, CSignedEncodeMsg_GetParam
,
1359 CSignedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1360 msg
->data
.cbData
= 0;
1361 msg
->data
.pbData
= NULL
;
1362 msg
->msg_data
.info
= CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO
));
1363 if (msg
->msg_data
.info
)
1365 memset(msg
->msg_data
.info
, 0, sizeof(CRYPT_SIGNED_INFO
));
1366 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V1
;
1374 msg
->msg_data
.info
->rgSignerInfo
=
1375 CryptMemAlloc(info
->cSigners
* sizeof(CMSG_CMS_SIGNER_INFO
));
1376 if (msg
->msg_data
.info
->rgSignerInfo
)
1378 msg
->msg_data
.info
->cSignerInfo
= info
->cSigners
;
1379 memset(msg
->msg_data
.info
->rgSignerInfo
, 0,
1380 msg
->msg_data
.info
->cSignerInfo
*
1381 sizeof(CMSG_CMS_SIGNER_INFO
));
1382 ret
= CSignedMsgData_AllocateHandles(&msg
->msg_data
);
1383 for (i
= 0; ret
&& i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1385 if (info
->rgSigners
[i
].SignerId
.dwIdChoice
==
1386 CERT_ID_KEY_IDENTIFIER
)
1387 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V3
;
1388 ret
= CSignerInfo_Construct(
1389 &msg
->msg_data
.info
->rgSignerInfo
[i
],
1390 &info
->rgSigners
[i
]);
1393 ret
= CSignedMsgData_ConstructSignerHandles(
1394 &msg
->msg_data
, i
, info
->rgSigners
[i
].hCryptProv
);
1395 if (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1396 CryptReleaseContext(info
->rgSigners
[i
].hCryptProv
,
1406 msg
->msg_data
.info
->cSignerInfo
= 0;
1407 msg
->msg_data
.signerHandles
= NULL
;
1408 msg
->msg_data
.cSignerHandle
= 0;
1412 ret
= CRYPT_ConstructBlobArray(
1413 (BlobArray
*)&msg
->msg_data
.info
->cCertEncoded
,
1414 (const BlobArray
*)&info
->cCertEncoded
);
1416 ret
= CRYPT_ConstructBlobArray(
1417 (BlobArray
*)&msg
->msg_data
.info
->cCrlEncoded
,
1418 (const BlobArray
*)&info
->cCrlEncoded
);
1421 CSignedEncodeMsg_Close(msg
);
1428 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
1429 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
1430 PCMSG_STREAM_INFO pStreamInfo
)
1432 HCRYPTMSG msg
= NULL
;
1434 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
1435 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
1437 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
1439 SetLastError(E_INVALIDARG
);
1445 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1446 pszInnerContentObjID
, pStreamInfo
);
1449 msg
= CHashEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1450 pszInnerContentObjID
, pStreamInfo
);
1453 msg
= CSignedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1454 pszInnerContentObjID
, pStreamInfo
);
1456 case CMSG_ENVELOPED
:
1457 FIXME("unimplemented for type CMSG_ENVELOPED\n");
1459 case CMSG_SIGNED_AND_ENVELOPED
:
1460 case CMSG_ENCRYPTED
:
1461 /* defined but invalid, fall through */
1463 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1468 typedef struct _CDecodeMsg
1472 HCRYPTPROV crypt_prov
;
1475 CSignedMsgData signed_data
;
1477 CRYPT_DATA_BLOB msg_data
;
1478 CRYPT_DATA_BLOB detached_data
;
1479 PCONTEXT_PROPERTY_LIST properties
;
1482 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg
)
1484 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
1486 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1487 CryptReleaseContext(msg
->crypt_prov
, 0);
1492 CryptDestroyHash(msg
->u
.hash
);
1495 if (msg
->u
.signed_data
.info
)
1497 LocalFree(msg
->u
.signed_data
.info
);
1498 CSignedMsgData_CloseHandles(&msg
->u
.signed_data
);
1502 CryptMemFree(msg
->msg_data
.pbData
);
1503 CryptMemFree(msg
->detached_data
.pbData
);
1504 ContextPropertyList_Free(msg
->properties
);
1507 static BOOL
CDecodeMsg_CopyData(CRYPT_DATA_BLOB
*blob
, const BYTE
*pbData
,
1515 blob
->pbData
= CryptMemRealloc(blob
->pbData
,
1516 blob
->cbData
+ cbData
);
1518 blob
->pbData
= CryptMemAlloc(cbData
);
1521 memcpy(blob
->pbData
+ blob
->cbData
, pbData
, cbData
);
1522 blob
->cbData
+= cbData
;
1530 static BOOL
CDecodeMsg_DecodeDataContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
1533 CRYPT_DATA_BLOB
*data
;
1536 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1537 blob
->pbData
, blob
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&data
,
1541 ret
= ContextPropertyList_SetProperty(msg
->properties
,
1542 CMSG_CONTENT_PARAM
, data
->pbData
, data
->cbData
);
1548 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg
*msg
, DWORD param
,
1549 const CRYPT_ALGORITHM_IDENTIFIER
*id
)
1551 static const BYTE nullParams
[] = { ASN_NULL
, 0 };
1552 CRYPT_ALGORITHM_IDENTIFIER
*copy
;
1553 DWORD len
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
1555 /* Linearize algorithm id */
1556 len
+= strlen(id
->pszObjId
) + 1;
1557 len
+= id
->Parameters
.cbData
;
1558 copy
= CryptMemAlloc(len
);
1562 (LPSTR
)((BYTE
*)copy
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
1563 strcpy(copy
->pszObjId
, id
->pszObjId
);
1564 copy
->Parameters
.pbData
= (BYTE
*)copy
->pszObjId
+ strlen(id
->pszObjId
)
1566 /* Trick: omit NULL parameters */
1567 if (id
->Parameters
.cbData
== sizeof(nullParams
) &&
1568 !memcmp(id
->Parameters
.pbData
, nullParams
, sizeof(nullParams
)))
1570 copy
->Parameters
.cbData
= 0;
1571 len
-= sizeof(nullParams
);
1574 copy
->Parameters
.cbData
= id
->Parameters
.cbData
;
1575 if (copy
->Parameters
.cbData
)
1576 memcpy(copy
->Parameters
.pbData
, id
->Parameters
.pbData
,
1577 id
->Parameters
.cbData
);
1578 ContextPropertyList_SetProperty(msg
->properties
, param
, (BYTE
*)copy
,
1584 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER
*id
)
1586 id
->pszObjId
= (LPSTR
)((BYTE
*)id
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
1587 id
->Parameters
.pbData
= (BYTE
*)id
->pszObjId
+ strlen(id
->pszObjId
) + 1;
1590 static BOOL
CDecodeMsg_DecodeHashedContent(CDecodeMsg
*msg
,
1591 CRYPT_DER_BLOB
*blob
)
1594 CRYPT_DIGESTED_DATA
*digestedData
;
1597 ret
= CRYPT_AsnDecodePKCSDigestedData(blob
->pbData
, blob
->cbData
,
1598 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_DIGESTED_DATA
*)&digestedData
,
1602 ContextPropertyList_SetProperty(msg
->properties
, CMSG_VERSION_PARAM
,
1603 (const BYTE
*)&digestedData
->version
, sizeof(digestedData
->version
));
1604 CDecodeMsg_SaveAlgorithmID(msg
, CMSG_HASH_ALGORITHM_PARAM
,
1605 &digestedData
->DigestAlgorithm
);
1606 ContextPropertyList_SetProperty(msg
->properties
,
1607 CMSG_INNER_CONTENT_TYPE_PARAM
,
1608 (const BYTE
*)digestedData
->ContentInfo
.pszObjId
,
1609 digestedData
->ContentInfo
.pszObjId
?
1610 strlen(digestedData
->ContentInfo
.pszObjId
) + 1 : 0);
1611 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1613 if (digestedData
->ContentInfo
.Content
.cbData
)
1614 CDecodeMsg_DecodeDataContent(msg
,
1615 &digestedData
->ContentInfo
.Content
);
1617 ContextPropertyList_SetProperty(msg
->properties
,
1618 CMSG_CONTENT_PARAM
, NULL
, 0);
1620 ContextPropertyList_SetProperty(msg
->properties
, CMSG_HASH_DATA_PARAM
,
1621 digestedData
->hash
.pbData
, digestedData
->hash
.cbData
);
1622 LocalFree(digestedData
);
1627 static BOOL
CDecodeMsg_DecodeSignedContent(CDecodeMsg
*msg
,
1628 CRYPT_DER_BLOB
*blob
)
1631 CRYPT_SIGNED_INFO
*signedInfo
;
1634 ret
= CRYPT_AsnDecodeCMSSignedInfo(blob
->pbData
, blob
->cbData
,
1635 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_SIGNED_INFO
*)&signedInfo
,
1638 msg
->u
.signed_data
.info
= signedInfo
;
1642 /* Decodes the content in blob as the type given, and updates the value
1643 * (type, parameters, etc.) of msg based on what blob contains.
1644 * It doesn't just use msg's type, to allow a recursive call from an implicitly
1645 * typed message once the outer content info has been decoded.
1647 static BOOL
CDecodeMsg_DecodeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
,
1655 if ((ret
= CDecodeMsg_DecodeDataContent(msg
, blob
)))
1656 msg
->type
= CMSG_DATA
;
1659 if ((ret
= CDecodeMsg_DecodeHashedContent(msg
, blob
)))
1660 msg
->type
= CMSG_HASHED
;
1662 case CMSG_ENVELOPED
:
1663 FIXME("unimplemented for type CMSG_ENVELOPED\n");
1667 if ((ret
= CDecodeMsg_DecodeSignedContent(msg
, blob
)))
1668 msg
->type
= CMSG_SIGNED
;
1672 CRYPT_CONTENT_INFO
*info
;
1675 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
,
1676 msg
->msg_data
.pbData
, msg
->msg_data
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
1677 NULL
, (LPBYTE
)&info
, &size
);
1680 if (!strcmp(info
->pszObjId
, szOID_RSA_data
))
1681 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
, CMSG_DATA
);
1682 else if (!strcmp(info
->pszObjId
, szOID_RSA_digestedData
))
1683 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1685 else if (!strcmp(info
->pszObjId
, szOID_RSA_envelopedData
))
1686 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1688 else if (!strcmp(info
->pszObjId
, szOID_RSA_signedData
))
1689 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1693 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1703 static BOOL
CDecodeMsg_FinalizeHashedContent(CDecodeMsg
*msg
,
1704 CRYPT_DER_BLOB
*blob
)
1706 CRYPT_ALGORITHM_IDENTIFIER
*hashAlgoID
= NULL
;
1711 CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, NULL
, &size
);
1712 hashAlgoID
= CryptMemAlloc(size
);
1713 ret
= CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, hashAlgoID
,
1716 algID
= CertOIDToAlgId(hashAlgoID
->pszObjId
);
1717 ret
= CryptCreateHash(msg
->crypt_prov
, algID
, 0, 0, &msg
->u
.hash
);
1720 CRYPT_DATA_BLOB content
;
1722 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1724 /* Unlike for non-detached messages, the data were never stored as
1725 * the content param, but were saved in msg->detached_data instead.
1727 content
.pbData
= msg
->detached_data
.pbData
;
1728 content
.cbData
= msg
->detached_data
.cbData
;
1731 ret
= ContextPropertyList_FindProperty(msg
->properties
,
1732 CMSG_CONTENT_PARAM
, &content
);
1734 ret
= CryptHashData(msg
->u
.hash
, content
.pbData
, content
.cbData
, 0);
1736 CryptMemFree(hashAlgoID
);
1740 static BOOL
CDecodeMsg_FinalizeSignedContent(CDecodeMsg
*msg
,
1741 CRYPT_DER_BLOB
*blob
)
1746 ret
= CSignedMsgData_AllocateHandles(&msg
->u
.signed_data
);
1747 for (i
= 0; ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
1748 ret
= CSignedMsgData_ConstructSignerHandles(&msg
->u
.signed_data
, i
,
1752 CRYPT_DATA_BLOB
*content
;
1754 /* Now that we have all the content, update the hash handles with
1755 * it. If the message is a detached message, the content is stored
1756 * in msg->detached_data rather than in the signed message's
1759 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1760 content
= &msg
->detached_data
;
1762 content
= &msg
->u
.signed_data
.info
->content
.Content
;
1763 if (content
->cbData
)
1765 /* If the message is not detached, have to decode the message's
1766 * content if the type is szOID_RSA_data.
1768 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) &&
1769 !strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
1772 CRYPT_DATA_BLOB
*blob
;
1774 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
,
1775 X509_OCTET_STRING
, content
->pbData
, content
->cbData
,
1776 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&blob
, &size
);
1779 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
1780 blob
->pbData
, blob
->cbData
, TRUE
, Verify
);
1785 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
1786 content
->pbData
, content
->cbData
, TRUE
, Verify
);
1792 static BOOL
CDecodeMsg_FinalizeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
1799 ret
= CDecodeMsg_FinalizeHashedContent(msg
, blob
);
1802 ret
= CDecodeMsg_FinalizeSignedContent(msg
, blob
);
1810 static BOOL
CDecodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1811 DWORD cbData
, BOOL fFinal
)
1813 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
1816 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
1818 if (msg
->base
.state
== MsgStateFinalized
)
1819 SetLastError(CRYPT_E_MSG_ERROR
);
1820 else if (msg
->base
.streamed
)
1822 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg
, pbData
,
1824 switch (msg
->base
.state
)
1827 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
1830 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1831 msg
->base
.state
= MsgStateDataFinalized
;
1833 msg
->base
.state
= MsgStateFinalized
;
1836 msg
->base
.state
= MsgStateUpdated
;
1838 case MsgStateUpdated
:
1839 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
1842 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1843 msg
->base
.state
= MsgStateDataFinalized
;
1845 msg
->base
.state
= MsgStateFinalized
;
1848 case MsgStateDataFinalized
:
1849 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
1851 msg
->base
.state
= MsgStateFinalized
;
1854 SetLastError(CRYPT_E_MSG_ERROR
);
1861 SetLastError(CRYPT_E_MSG_ERROR
);
1864 switch (msg
->base
.state
)
1867 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
1868 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1869 msg
->base
.state
= MsgStateDataFinalized
;
1871 msg
->base
.state
= MsgStateFinalized
;
1873 case MsgStateDataFinalized
:
1874 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
1875 msg
->base
.state
= MsgStateFinalized
;
1878 SetLastError(CRYPT_E_MSG_ERROR
);
1882 if (ret
&& fFinal
&&
1883 ((msg
->base
.open_flags
& CMSG_DETACHED_FLAG
&& msg
->base
.state
==
1884 MsgStateDataFinalized
) ||
1885 (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->base
.state
==
1886 MsgStateFinalized
)))
1887 ret
= CDecodeMsg_DecodeContent(msg
, &msg
->msg_data
, msg
->type
);
1888 if (ret
&& msg
->base
.state
== MsgStateFinalized
)
1889 ret
= CDecodeMsg_FinalizeContent(msg
, &msg
->msg_data
);
1893 static BOOL
CDecodeHashMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
1894 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1898 switch (dwParamType
)
1900 case CMSG_TYPE_PARAM
:
1901 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
1903 case CMSG_HASH_ALGORITHM_PARAM
:
1905 CRYPT_DATA_BLOB blob
;
1907 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
1911 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
1913 CRYPT_FixUpAlgorithmID((CRYPT_ALGORITHM_IDENTIFIER
*)pvData
);
1916 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1919 case CMSG_COMPUTED_HASH_PARAM
:
1920 ret
= CryptGetHashParam(msg
->u
.hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
1924 CRYPT_DATA_BLOB blob
;
1926 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
1929 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
1931 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1937 /* nextData is an in/out parameter - on input it's the memory location in
1938 * which a copy of in's data should be made, and on output it's the memory
1939 * location immediately after out's copy of in's data.
1941 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB
*out
,
1942 const CRYPT_DATA_BLOB
*in
, LPBYTE
*nextData
)
1944 out
->cbData
= in
->cbData
;
1947 out
->pbData
= *nextData
;
1948 memcpy(out
->pbData
, in
->pbData
, in
->cbData
);
1949 *nextData
+= in
->cbData
;
1953 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
1954 const CRYPT_ALGORITHM_IDENTIFIER
*in
, LPBYTE
*nextData
)
1958 out
->pszObjId
= (LPSTR
)*nextData
;
1959 strcpy(out
->pszObjId
, in
->pszObjId
);
1960 *nextData
+= strlen(out
->pszObjId
) + 1;
1962 CRYPT_CopyBlob(&out
->Parameters
, &in
->Parameters
, nextData
);
1965 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES
*out
,
1966 const CRYPT_ATTRIBUTES
*in
, LPBYTE
*nextData
)
1968 out
->cAttr
= in
->cAttr
;
1973 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
1974 out
->rgAttr
= (CRYPT_ATTRIBUTE
*)*nextData
;
1975 *nextData
+= in
->cAttr
* sizeof(CRYPT_ATTRIBUTE
);
1976 for (i
= 0; i
< in
->cAttr
; i
++)
1978 if (in
->rgAttr
[i
].pszObjId
)
1980 out
->rgAttr
[i
].pszObjId
= (LPSTR
)*nextData
;
1981 strcpy(out
->rgAttr
[i
].pszObjId
, in
->rgAttr
[i
].pszObjId
);
1982 *nextData
+= strlen(in
->rgAttr
[i
].pszObjId
) + 1;
1984 if (in
->rgAttr
[i
].cValue
)
1988 out
->rgAttr
[i
].cValue
= in
->rgAttr
[i
].cValue
;
1989 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
1990 out
->rgAttr
[i
].rgValue
= (PCRYPT_DATA_BLOB
)*nextData
;
1991 *nextData
+= in
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
1992 for (j
= 0; j
< in
->rgAttr
[i
].cValue
; j
++)
1993 CRYPT_CopyBlob(&out
->rgAttr
[i
].rgValue
[j
],
1994 &in
->rgAttr
[i
].rgValue
[j
], nextData
);
2000 static DWORD
CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES
*attr
)
2002 DWORD size
= attr
->cAttr
* sizeof(CRYPT_ATTRIBUTE
), i
, j
;
2004 for (i
= 0; i
< attr
->cAttr
; i
++)
2006 if (attr
->rgAttr
[i
].pszObjId
)
2007 size
+= strlen(attr
->rgAttr
[i
].pszObjId
) + 1;
2009 size
= ALIGN_DWORD_PTR(size
);
2010 size
+= attr
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2011 for (j
= 0; j
< attr
->rgAttr
[i
].cValue
; j
++)
2012 size
+= attr
->rgAttr
[i
].rgValue
[j
].cbData
;
2014 /* align pointer again to be conservative */
2015 size
= ALIGN_DWORD_PTR(size
);
2019 static DWORD
CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB
*keyId
)
2021 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2024 CERT_RDN rdn
= { 1, &attr
};
2025 CERT_NAME_INFO name
= { 1, &rdn
};
2027 attr
.pszObjId
= oid_key_rdn
;
2028 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2029 attr
.Value
.cbData
= keyId
->cbData
;
2030 attr
.Value
.pbData
= keyId
->pbData
;
2031 if (CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, NULL
, &size
))
2032 size
++; /* Only include size of special zero serial number on success */
2036 static BOOL
CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB
*issuer
,
2037 CRYPT_INTEGER_BLOB
*serialNumber
, const CRYPT_DATA_BLOB
*keyId
, DWORD encodedLen
,
2040 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2042 CERT_RDN rdn
= { 1, &attr
};
2043 CERT_NAME_INFO name
= { 1, &rdn
};
2046 /* Encode special zero serial number */
2047 serialNumber
->cbData
= 1;
2048 serialNumber
->pbData
= *nextData
;
2052 issuer
->pbData
= *nextData
;
2053 attr
.pszObjId
= oid_key_rdn
;
2054 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2055 attr
.Value
.cbData
= keyId
->cbData
;
2056 attr
.Value
.pbData
= keyId
->pbData
;
2057 ret
= CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, *nextData
,
2061 *nextData
+= encodedLen
;
2062 issuer
->cbData
= encodedLen
;
2067 static BOOL
CRYPT_CopySignerInfo(void *pvData
, DWORD
*pcbData
,
2068 const CMSG_CMS_SIGNER_INFO
*in
)
2070 DWORD size
= sizeof(CMSG_SIGNER_INFO
), rdnSize
= 0;
2073 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2075 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2077 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2078 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2082 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2085 if (in
->HashAlgorithm
.pszObjId
)
2086 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2087 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2088 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2089 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2090 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2091 size
+= in
->EncryptedHash
.cbData
;
2093 size
= ALIGN_DWORD_PTR(size
);
2094 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2095 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2101 else if (*pcbData
< size
)
2104 SetLastError(ERROR_MORE_DATA
);
2109 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_SIGNER_INFO
);
2110 CMSG_SIGNER_INFO
*out
= (CMSG_SIGNER_INFO
*)pvData
;
2113 out
->dwVersion
= in
->dwVersion
;
2114 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2116 CRYPT_CopyBlob(&out
->Issuer
,
2117 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2118 CRYPT_CopyBlob(&out
->SerialNumber
,
2119 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2122 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2123 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2126 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2128 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2129 &in
->HashEncryptionAlgorithm
, &nextData
);
2130 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2131 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2132 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2133 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2136 TRACE("returning %d\n", ret
);
2140 static BOOL
CRYPT_CopyCMSSignerInfo(void *pvData
, DWORD
*pcbData
,
2141 const CMSG_CMS_SIGNER_INFO
*in
)
2143 DWORD size
= sizeof(CMSG_CMS_SIGNER_INFO
);
2146 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2148 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2150 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2151 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2154 size
+= in
->SignerId
.u
.KeyId
.cbData
;
2155 if (in
->HashAlgorithm
.pszObjId
)
2156 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2157 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2158 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2159 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2160 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2161 size
+= in
->EncryptedHash
.cbData
;
2163 size
= ALIGN_DWORD_PTR(size
);
2164 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2165 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2171 else if (*pcbData
< size
)
2174 SetLastError(ERROR_MORE_DATA
);
2179 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_CMS_SIGNER_INFO
);
2180 CMSG_CMS_SIGNER_INFO
*out
= (CMSG_CMS_SIGNER_INFO
*)pvData
;
2182 out
->dwVersion
= in
->dwVersion
;
2183 out
->SignerId
.dwIdChoice
= in
->SignerId
.dwIdChoice
;
2184 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2186 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
2187 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2188 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
2189 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2192 CRYPT_CopyBlob(&out
->SignerId
.u
.KeyId
, &in
->SignerId
.u
.KeyId
, &nextData
);
2193 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2195 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2196 &in
->HashEncryptionAlgorithm
, &nextData
);
2197 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2198 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2199 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2200 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2203 TRACE("returning %d\n", ret
);
2207 static BOOL
CRYPT_CopySignerCertInfo(void *pvData
, DWORD
*pcbData
,
2208 const CMSG_CMS_SIGNER_INFO
*in
)
2210 DWORD size
= sizeof(CERT_INFO
), rdnSize
= 0;
2213 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2215 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2217 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2218 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2222 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2230 else if (*pcbData
< size
)
2233 SetLastError(ERROR_MORE_DATA
);
2238 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2239 CERT_INFO
*out
= (CERT_INFO
*)pvData
;
2241 memset(out
, 0, sizeof(CERT_INFO
));
2242 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2244 CRYPT_CopyBlob(&out
->Issuer
,
2245 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2246 CRYPT_CopyBlob(&out
->SerialNumber
,
2247 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2251 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2252 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2254 TRACE("returning %d\n", ret
);
2258 static BOOL
CDecodeSignedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2259 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2263 switch (dwParamType
)
2265 case CMSG_TYPE_PARAM
:
2266 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2268 case CMSG_CONTENT_PARAM
:
2269 if (msg
->u
.signed_data
.info
)
2271 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2274 CRYPT_DATA_BLOB
*blob
;
2277 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
2278 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
2279 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
2280 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&blob
, &size
);
2283 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
->pbData
,
2289 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2290 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
2291 msg
->u
.signed_data
.info
->content
.Content
.cbData
);
2294 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2296 case CMSG_INNER_CONTENT_TYPE_PARAM
:
2297 if (msg
->u
.signed_data
.info
)
2298 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2299 msg
->u
.signed_data
.info
->content
.pszObjId
,
2300 strlen(msg
->u
.signed_data
.info
->content
.pszObjId
) + 1);
2302 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2304 case CMSG_SIGNER_COUNT_PARAM
:
2305 if (msg
->u
.signed_data
.info
)
2306 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2307 &msg
->u
.signed_data
.info
->cSignerInfo
, sizeof(DWORD
));
2309 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2311 case CMSG_SIGNER_INFO_PARAM
:
2312 if (msg
->u
.signed_data
.info
)
2314 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2315 SetLastError(CRYPT_E_INVALID_INDEX
);
2317 ret
= CRYPT_CopySignerInfo(pvData
, pcbData
,
2318 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
2321 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2323 case CMSG_SIGNER_CERT_INFO_PARAM
:
2324 if (msg
->u
.signed_data
.info
)
2326 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2327 SetLastError(CRYPT_E_INVALID_INDEX
);
2329 ret
= CRYPT_CopySignerCertInfo(pvData
, pcbData
,
2330 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
2333 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2335 case CMSG_CERT_COUNT_PARAM
:
2336 if (msg
->u
.signed_data
.info
)
2337 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2338 &msg
->u
.signed_data
.info
->cCertEncoded
, sizeof(DWORD
));
2340 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2342 case CMSG_CERT_PARAM
:
2343 if (msg
->u
.signed_data
.info
)
2345 if (dwIndex
>= msg
->u
.signed_data
.info
->cCertEncoded
)
2346 SetLastError(CRYPT_E_INVALID_INDEX
);
2348 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2349 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].pbData
,
2350 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].cbData
);
2353 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2355 case CMSG_CRL_COUNT_PARAM
:
2356 if (msg
->u
.signed_data
.info
)
2357 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2358 &msg
->u
.signed_data
.info
->cCrlEncoded
, sizeof(DWORD
));
2360 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2362 case CMSG_CRL_PARAM
:
2363 if (msg
->u
.signed_data
.info
)
2365 if (dwIndex
>= msg
->u
.signed_data
.info
->cCrlEncoded
)
2366 SetLastError(CRYPT_E_INVALID_INDEX
);
2368 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2369 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].pbData
,
2370 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].cbData
);
2373 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2375 case CMSG_COMPUTED_HASH_PARAM
:
2376 if (msg
->u
.signed_data
.info
)
2378 if (dwIndex
>= msg
->u
.signed_data
.cSignerHandle
)
2379 SetLastError(CRYPT_E_INVALID_INDEX
);
2381 ret
= CryptGetHashParam(
2382 msg
->u
.signed_data
.signerHandles
[dwIndex
].contentHash
,
2383 HP_HASHVAL
, pvData
, pcbData
, 0);
2386 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2388 case CMSG_ATTR_CERT_COUNT_PARAM
:
2389 if (msg
->u
.signed_data
.info
)
2391 DWORD attrCertCount
= 0;
2393 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2394 &attrCertCount
, sizeof(DWORD
));
2397 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2399 case CMSG_ATTR_CERT_PARAM
:
2400 if (msg
->u
.signed_data
.info
)
2401 SetLastError(CRYPT_E_INVALID_INDEX
);
2403 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2405 case CMSG_CMS_SIGNER_INFO_PARAM
:
2406 if (msg
->u
.signed_data
.info
)
2408 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2409 SetLastError(CRYPT_E_INVALID_INDEX
);
2411 ret
= CRYPT_CopyCMSSignerInfo(pvData
, pcbData
,
2412 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
2415 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2418 FIXME("unimplemented for %d\n", dwParamType
);
2419 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2424 static BOOL
CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
2425 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2427 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
2433 ret
= CDecodeHashMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2437 ret
= CDecodeSignedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2441 switch (dwParamType
)
2443 case CMSG_TYPE_PARAM
:
2444 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
,
2449 CRYPT_DATA_BLOB blob
;
2451 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2454 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
,
2457 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2464 static BOOL
CDecodeHashMsg_VerifyHash(CDecodeMsg
*msg
)
2467 CRYPT_DATA_BLOB hashBlob
;
2469 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2470 CMSG_HASH_DATA_PARAM
, &hashBlob
);
2473 DWORD computedHashSize
= 0;
2475 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
,
2477 if (hashBlob
.cbData
== computedHashSize
)
2479 LPBYTE computedHash
= CryptMemAlloc(computedHashSize
);
2483 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
2484 computedHash
, &computedHashSize
);
2487 if (memcmp(hashBlob
.pbData
, computedHash
, hashBlob
.cbData
))
2489 SetLastError(CRYPT_E_HASH_VALUE
);
2493 CryptMemFree(computedHash
);
2497 SetLastError(ERROR_OUTOFMEMORY
);
2503 SetLastError(CRYPT_E_HASH_VALUE
);
2510 static BOOL
CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg
*msg
,
2511 HCRYPTPROV prov
, DWORD signerIndex
, PCERT_PUBLIC_KEY_INFO keyInfo
)
2517 prov
= msg
->crypt_prov
;
2518 ret
= CryptImportPublicKeyInfo(prov
, X509_ASN_ENCODING
, keyInfo
, &key
);
2522 CRYPT_HASH_BLOB reversedHash
;
2524 if (msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
)
2525 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].authAttrHash
;
2527 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].contentHash
;
2528 ret
= CRYPT_ConstructBlob(&reversedHash
,
2529 &msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].EncryptedHash
);
2532 CRYPT_ReverseBytes(&reversedHash
);
2533 ret
= CryptVerifySignatureW(hash
, reversedHash
.pbData
,
2534 reversedHash
.cbData
, key
, NULL
, 0);
2535 CryptMemFree(reversedHash
.pbData
);
2537 CryptDestroyKey(key
);
2542 static BOOL
CDecodeSignedMsg_VerifySignature(CDecodeMsg
*msg
, PCERT_INFO info
)
2547 if (!msg
->u
.signed_data
.signerHandles
)
2549 SetLastError(NTE_BAD_SIGNATURE
);
2552 for (i
= 0; !ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
2554 PCMSG_CMS_SIGNER_INFO signerInfo
=
2555 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
];
2557 if (signerInfo
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2559 ret
= CertCompareCertificateName(X509_ASN_ENCODING
,
2560 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
2564 ret
= CertCompareIntegerBlob(
2565 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
2566 &info
->SerialNumber
);
2573 FIXME("signer %d: unimplemented for key id\n", i
);
2577 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, 0, i
,
2578 &info
->SubjectPublicKeyInfo
);
2580 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2585 static BOOL
CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg
*msg
,
2586 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para
)
2590 if (para
->cbSize
!= sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
))
2591 SetLastError(ERROR_INVALID_PARAMETER
);
2592 else if (para
->dwSignerIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2593 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2594 else if (!msg
->u
.signed_data
.signerHandles
)
2595 SetLastError(NTE_BAD_SIGNATURE
);
2598 switch (para
->dwSignerType
)
2600 case CMSG_VERIFY_SIGNER_PUBKEY
:
2601 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
,
2602 para
->hCryptProv
, para
->dwSignerIndex
,
2603 (PCERT_PUBLIC_KEY_INFO
)para
->pvSigner
);
2605 case CMSG_VERIFY_SIGNER_CERT
:
2607 PCCERT_CONTEXT cert
= (PCCERT_CONTEXT
)para
->pvSigner
;
2609 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, para
->hCryptProv
,
2610 para
->dwSignerIndex
, &cert
->pCertInfo
->SubjectPublicKeyInfo
);
2614 FIXME("unimplemented for signer type %d\n", para
->dwSignerType
);
2615 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2621 static BOOL
CDecodeMsg_Control(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
2622 DWORD dwCtrlType
, const void *pvCtrlPara
)
2624 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
2629 case CMSG_CTRL_VERIFY_SIGNATURE
:
2633 ret
= CDecodeSignedMsg_VerifySignature(msg
, (PCERT_INFO
)pvCtrlPara
);
2636 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2639 case CMSG_CTRL_DECRYPT
:
2643 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2646 case CMSG_CTRL_VERIFY_HASH
:
2650 ret
= CDecodeHashMsg_VerifyHash(msg
);
2653 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2656 case CMSG_CTRL_VERIFY_SIGNATURE_EX
:
2660 ret
= CDecodeSignedMsg_VerifySignatureEx(msg
,
2661 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
)pvCtrlPara
);
2664 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2668 SetLastError(CRYPT_E_CONTROL_TYPE
);
2673 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
2674 DWORD dwMsgType
, HCRYPTPROV_LEGACY hCryptProv
, PCERT_INFO pRecipientInfo
,
2675 PCMSG_STREAM_INFO pStreamInfo
)
2679 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType
,
2680 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
2682 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
2684 SetLastError(E_INVALIDARG
);
2687 msg
= CryptMemAlloc(sizeof(CDecodeMsg
));
2690 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
2691 CDecodeMsg_Close
, CDecodeMsg_GetParam
, CDecodeMsg_Update
,
2692 CDecodeMsg_Control
);
2693 msg
->type
= dwMsgType
;
2695 msg
->crypt_prov
= hCryptProv
;
2698 msg
->crypt_prov
= CRYPT_GetDefaultProvider();
2699 msg
->base
.open_flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
2701 memset(&msg
->u
, 0, sizeof(msg
->u
));
2702 msg
->msg_data
.cbData
= 0;
2703 msg
->msg_data
.pbData
= NULL
;
2704 msg
->detached_data
.cbData
= 0;
2705 msg
->detached_data
.pbData
= NULL
;
2706 msg
->properties
= ContextPropertyList_Create();
2711 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
2713 TRACE("(%p)\n", hCryptMsg
);
2717 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2719 InterlockedIncrement(&msg
->ref
);
2724 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
2726 TRACE("(%p)\n", hCryptMsg
);
2730 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2732 if (InterlockedDecrement(&msg
->ref
) == 0)
2734 TRACE("freeing %p\n", msg
);
2743 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
2744 DWORD cbData
, BOOL fFinal
)
2746 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2748 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
2750 return msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
2753 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
2754 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2756 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2758 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
2760 return msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);
2763 BOOL WINAPI
CryptMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
2764 DWORD dwCtrlType
, const void *pvCtrlPara
)
2766 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2768 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
,
2770 return msg
->control(hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
2773 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
2774 DWORD dwSignerIndex
)
2776 CERT_INFO
*certInfo
= NULL
;
2779 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
2782 certInfo
= CryptMemAlloc(size
);
2785 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
2786 dwSignerIndex
, certInfo
, &size
))
2788 CryptMemFree(certInfo
);
2796 BOOL WINAPI
CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg
, DWORD cSignerStore
,
2797 HCERTSTORE
*rghSignerStore
, DWORD dwFlags
, PCCERT_CONTEXT
*ppSigner
,
2798 DWORD
*pdwSignerIndex
)
2801 DWORD i
, signerIndex
= 0;
2802 PCCERT_CONTEXT signerCert
= NULL
;
2805 TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg
, cSignerStore
,
2806 rghSignerStore
, dwFlags
, ppSigner
, pdwSignerIndex
);
2808 /* Clear output parameters */
2811 if (pdwSignerIndex
&& !(dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
))
2812 *pdwSignerIndex
= 0;
2814 /* Create store to search for signer certificates */
2815 store
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
2816 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
2817 if (!(dwFlags
& CMSG_TRUSTED_SIGNER_FLAG
))
2819 HCERTSTORE msgStore
= CertOpenStore(CERT_STORE_PROV_MSG
, 0, 0, 0,
2822 CertAddStoreToCollection(store
, msgStore
, 0, 0);
2823 CertCloseStore(msgStore
, 0);
2825 for (i
= 0; i
< cSignerStore
; i
++)
2826 CertAddStoreToCollection(store
, rghSignerStore
[i
], 0, 0);
2828 /* Find signer cert */
2829 if (dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
)
2831 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
2836 signerIndex
= *pdwSignerIndex
;
2837 signerCert
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
,
2838 0, CERT_FIND_SUBJECT_CERT
, signer
, NULL
);
2839 CryptMemFree(signer
);
2844 DWORD count
, size
= sizeof(count
);
2846 if (CryptMsgGetParam(hCryptMsg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
,
2849 for (i
= 0; !signerCert
&& i
< count
; i
++)
2851 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
2856 signerCert
= CertFindCertificateInStore(store
,
2857 X509_ASN_ENCODING
, 0, CERT_FIND_SUBJECT_CERT
, signer
,
2861 CryptMemFree(signer
);
2866 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER
);
2870 if (!(dwFlags
& CMSG_SIGNER_ONLY_FLAG
))
2871 ret
= CryptMsgControl(hCryptMsg
, 0, CMSG_CTRL_VERIFY_SIGNATURE
,
2872 signerCert
->pCertInfo
);
2878 *ppSigner
= CertDuplicateCertificateContext(signerCert
);
2880 *pdwSignerIndex
= signerIndex
;
2882 CertFreeCertificateContext(signerCert
);
2885 CertCloseStore(store
, 0);
2889 BOOL WINAPI
CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv
,
2890 DWORD dwEncodingType
, PBYTE pbSignerInfo
, DWORD cbSignerInfo
,
2891 PBYTE pbSignerInfoCountersignature
, DWORD cbSignerInfoCountersignature
,
2892 DWORD dwSignerType
, void *pvSigner
, DWORD dwFlags
, void *pvReserved
)
2894 FIXME("(%08lx, %08x, %p, %d, %p, %d, %d, %p, %08x, %p): stub\n", hCryptProv
,
2895 dwEncodingType
, pbSignerInfo
, cbSignerInfo
, pbSignerInfoCountersignature
,
2896 cbSignerInfoCountersignature
, dwSignerType
, pvSigner
, dwFlags
, pvReserved
);