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"
28 #include "wine/debug.h"
29 #include "wine/exception.h"
30 #include "crypt32_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
34 /* Called when a message's ref count reaches zero. Free any message-specific
37 typedef void (*CryptMsgCloseFunc
)(HCRYPTMSG msg
);
39 typedef BOOL (*CryptMsgGetParamFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
40 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
);
42 typedef BOOL (*CryptMsgUpdateFunc
)(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
43 DWORD cbData
, BOOL fFinal
);
45 typedef BOOL (*CryptMsgControlFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
46 DWORD dwCtrlType
, const void *pvCtrlPara
);
48 BOOL
CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
49 DWORD dwCtrlType
, const void *pvCtrlPara
)
51 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
52 SetLastError(E_INVALIDARG
);
56 typedef enum _CryptMsgState
{
59 MsgStateDataFinalized
,
63 typedef struct _CryptMsgBase
68 CMSG_STREAM_INFO stream_info
;
70 CryptMsgCloseFunc close
;
71 CryptMsgUpdateFunc update
;
72 CryptMsgGetParamFunc get_param
;
73 CryptMsgControlFunc control
;
76 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
77 PCMSG_STREAM_INFO pStreamInfo
, CryptMsgCloseFunc close
,
78 CryptMsgGetParamFunc get_param
, CryptMsgUpdateFunc update
,
79 CryptMsgControlFunc control
)
82 msg
->open_flags
= dwFlags
;
86 msg
->stream_info
= *pStreamInfo
;
90 msg
->streamed
= FALSE
;
91 memset(&msg
->stream_info
, 0, sizeof(msg
->stream_info
));
94 msg
->get_param
= get_param
;
96 msg
->control
= control
;
97 msg
->state
= MsgStateInit
;
100 typedef struct _CDataEncodeMsg
103 DWORD bare_content_len
;
107 static const BYTE empty_data_content
[] = { 0x04,0x00 };
109 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
111 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
113 if (msg
->bare_content
!= empty_data_content
)
114 LocalFree(msg
->bare_content
);
117 static BOOL WINAPI
CRYPT_EncodeContentLength(DWORD dwCertEncodingType
,
118 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
119 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
121 DWORD dataLen
= *(DWORD
*)pvStructInfo
;
125 /* Trick: report bytes needed based on total message length, even though
126 * the message isn't available yet. The caller will use the length
127 * reported here to encode its length.
129 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
131 *pcbEncoded
= 1 + lenBytes
+ dataLen
;
134 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
135 pcbEncoded
, 1 + lenBytes
)))
137 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
138 pbEncoded
= *(BYTE
**)pbEncoded
;
139 *pbEncoded
++ = ASN_OCTETSTRING
;
140 CRYPT_EncodeLen(dataLen
, pbEncoded
,
147 static BOOL
CRYPT_EncodeDataContentInfoHeader(CDataEncodeMsg
*msg
,
148 CRYPT_DATA_BLOB
*header
)
152 if (msg
->base
.streamed
&& msg
->base
.stream_info
.cbContent
== 0xffffffff)
154 static const BYTE headerValue
[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
155 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
157 header
->pbData
= LocalAlloc(0, sizeof(headerValue
));
160 header
->cbData
= sizeof(headerValue
);
161 memcpy(header
->pbData
, headerValue
, sizeof(headerValue
));
169 struct AsnConstructedItem constructed
= { 0,
170 &msg
->base
.stream_info
.cbContent
, CRYPT_EncodeContentLength
};
171 struct AsnEncodeSequenceItem items
[2] = {
172 { szOID_RSA_data
, CRYPT_AsnEncodeOid
, 0 },
173 { &constructed
, CRYPT_AsnEncodeConstructed
, 0 },
176 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
177 sizeof(items
) / sizeof(items
[0]), CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
178 (LPBYTE
)&header
->pbData
, &header
->cbData
);
181 /* Trick: subtract the content length from the reported length,
182 * as the actual content hasn't come yet.
184 header
->cbData
-= msg
->base
.stream_info
.cbContent
;
190 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
191 DWORD cbData
, BOOL fFinal
)
193 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
196 if (msg
->base
.state
== MsgStateFinalized
)
197 SetLastError(CRYPT_E_MSG_ERROR
);
198 else if (msg
->base
.streamed
)
202 if (msg
->base
.state
!= MsgStateUpdated
)
204 CRYPT_DATA_BLOB header
;
206 ret
= CRYPT_EncodeDataContentInfoHeader(msg
, &header
);
209 ret
= msg
->base
.stream_info
.pfnStreamOutput(
210 msg
->base
.stream_info
.pvArg
, header
.pbData
, header
.cbData
,
212 LocalFree(header
.pbData
);
215 /* Curiously, every indefinite-length streamed update appears to
216 * get its own tag and length, regardless of fFinal.
218 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
223 ret
= CRYPT_EncodeContentLength(X509_ASN_ENCODING
, NULL
,
224 &cbData
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (BYTE
*)&header
,
228 ret
= msg
->base
.stream_info
.pfnStreamOutput(
229 msg
->base
.stream_info
.pvArg
, header
, headerLen
,
236 ret
= msg
->base
.stream_info
.pfnStreamOutput(
237 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
239 msg
->base
.state
= MsgStateUpdated
;
243 msg
->base
.state
= MsgStateFinalized
;
244 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
246 BYTE indefinite_trailer
[6] = { 0 };
248 ret
= msg
->base
.stream_info
.pfnStreamOutput(
249 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
252 ret
= msg
->base
.stream_info
.pfnStreamOutput(
253 msg
->base
.stream_info
.pvArg
, indefinite_trailer
,
254 sizeof(indefinite_trailer
), TRUE
);
257 ret
= msg
->base
.stream_info
.pfnStreamOutput(
258 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
, TRUE
);
263 SetLastError(STATUS_ACCESS_VIOLATION
);
272 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
273 SetLastError(E_INVALIDARG
);
275 SetLastError(CRYPT_E_MSG_ERROR
);
279 msg
->base
.state
= MsgStateFinalized
;
281 SetLastError(E_INVALIDARG
);
284 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
286 /* non-streamed data messages don't allow non-final updates,
287 * don't bother checking whether data already exist, they can't.
289 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
290 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
291 &msg
->bare_content_len
);
298 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
305 else if (*pcbData
< len
)
308 SetLastError(ERROR_MORE_DATA
);
314 memcpy(pvData
, src
, len
);
319 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
320 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
322 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
327 case CMSG_CONTENT_PARAM
:
328 if (msg
->base
.streamed
)
329 SetLastError(E_INVALIDARG
);
332 CRYPT_CONTENT_INFO info
;
333 char rsa_data
[] = "1.2.840.113549.1.7.1";
335 info
.pszObjId
= rsa_data
;
336 info
.Content
.cbData
= msg
->bare_content_len
;
337 info
.Content
.pbData
= msg
->bare_content
;
338 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
342 case CMSG_BARE_CONTENT_PARAM
:
343 if (msg
->base
.streamed
)
344 SetLastError(E_INVALIDARG
);
346 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->bare_content
,
347 msg
->bare_content_len
);
350 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
355 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
356 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
362 SetLastError(E_INVALIDARG
);
365 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
368 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
369 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
,
370 CRYPT_DefaultMsgControl
);
371 msg
->bare_content_len
= sizeof(empty_data_content
);
372 msg
->bare_content
= (LPBYTE
)empty_data_content
;
374 return (HCRYPTMSG
)msg
;
377 typedef struct _CHashEncodeMsg
382 CRYPT_DATA_BLOB data
;
385 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
387 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
389 CryptMemFree(msg
->data
.pbData
);
390 CryptDestroyHash(msg
->hash
);
391 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
392 CryptReleaseContext(msg
->prov
, 0);
395 static BOOL
CRYPT_EncodePKCSDigestedData(CHashEncodeMsg
*msg
, void *pvData
,
400 DWORD size
= sizeof(algID
);
402 ret
= CryptGetHashParam(msg
->hash
, HP_ALGID
, (BYTE
*)&algID
, &size
, 0);
405 CRYPT_DIGESTED_DATA digestedData
= { 0 };
406 char oid_rsa_data
[] = szOID_RSA_data
;
408 digestedData
.version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
409 digestedData
.DigestAlgorithm
.pszObjId
= (LPSTR
)CertAlgIdToOID(algID
);
410 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
411 /* Quirk: OID is only encoded messages if an update has happened */
412 if (msg
->base
.state
!= MsgStateInit
)
413 digestedData
.ContentInfo
.pszObjId
= oid_rsa_data
;
414 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->data
.cbData
)
416 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &msg
->data
,
417 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
418 (LPBYTE
)&digestedData
.ContentInfo
.Content
.pbData
,
419 &digestedData
.ContentInfo
.Content
.cbData
);
421 if (msg
->base
.state
== MsgStateFinalized
)
423 size
= sizeof(DWORD
);
424 ret
= CryptGetHashParam(msg
->hash
, HP_HASHSIZE
,
425 (LPBYTE
)&digestedData
.hash
.cbData
, &size
, 0);
428 digestedData
.hash
.pbData
= CryptMemAlloc(
429 digestedData
.hash
.cbData
);
430 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
,
431 digestedData
.hash
.pbData
, &digestedData
.hash
.cbData
, 0);
435 ret
= CRYPT_AsnEncodePKCSDigestedData(&digestedData
, pvData
,
437 CryptMemFree(digestedData
.hash
.pbData
);
438 LocalFree(digestedData
.ContentInfo
.Content
.pbData
);
443 static BOOL
CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
444 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
446 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
449 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
454 case CMSG_BARE_CONTENT_PARAM
:
455 if (msg
->base
.streamed
)
456 SetLastError(E_INVALIDARG
);
458 ret
= CRYPT_EncodePKCSDigestedData(msg
, pvData
, pcbData
);
460 case CMSG_CONTENT_PARAM
:
462 CRYPT_CONTENT_INFO info
;
464 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
465 &info
.Content
.cbData
);
468 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
469 if (info
.Content
.pbData
)
471 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
472 info
.Content
.pbData
, &info
.Content
.cbData
);
475 char oid_rsa_hashed
[] = szOID_RSA_hashedData
;
477 info
.pszObjId
= oid_rsa_hashed
;
478 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
479 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
481 CryptMemFree(info
.Content
.pbData
);
488 case CMSG_COMPUTED_HASH_PARAM
:
489 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
, (BYTE
*)pvData
, pcbData
,
492 case CMSG_VERSION_PARAM
:
493 if (msg
->base
.state
!= MsgStateFinalized
)
494 SetLastError(CRYPT_E_MSG_ERROR
);
497 DWORD version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
499 /* Since the data are always encoded as octets, the version is
500 * always 0 (see rfc3852, section 7)
502 ret
= CRYPT_CopyParam(pvData
, pcbData
, &version
, sizeof(version
));
506 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
511 static BOOL
CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
512 DWORD cbData
, BOOL fFinal
)
514 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
517 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
519 if (msg
->base
.state
== MsgStateFinalized
)
520 SetLastError(CRYPT_E_MSG_ERROR
);
521 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
523 /* Doesn't do much, as stream output is never called, and you
524 * can't get the content.
526 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
527 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
532 SetLastError(CRYPT_E_MSG_ERROR
);
535 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
538 msg
->data
.pbData
= CryptMemAlloc(cbData
);
539 if (msg
->data
.pbData
)
541 memcpy(msg
->data
.pbData
+ msg
->data
.cbData
, pbData
, cbData
);
542 msg
->data
.cbData
+= cbData
;
547 msg
->base
.state
= MsgStateFinalized
;
553 static HCRYPTMSG
CHashEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
554 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
557 const CMSG_HASHED_ENCODE_INFO
*info
=
558 (const CMSG_HASHED_ENCODE_INFO
*)pvMsgEncodeInfo
;
562 if (info
->cbSize
!= sizeof(CMSG_HASHED_ENCODE_INFO
))
564 SetLastError(E_INVALIDARG
);
567 if (!(algID
= CertOIDToAlgId(info
->HashAlgorithm
.pszObjId
)))
569 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
572 if (info
->hCryptProv
)
573 prov
= info
->hCryptProv
;
576 prov
= CRYPT_GetDefaultProvider();
577 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
579 msg
= CryptMemAlloc(sizeof(CHashEncodeMsg
));
582 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
583 CHashEncodeMsg_Close
, CHashEncodeMsg_GetParam
, CHashEncodeMsg_Update
,
584 CRYPT_DefaultMsgControl
);
586 msg
->data
.cbData
= 0;
587 msg
->data
.pbData
= NULL
;
588 if (!CryptCreateHash(prov
, algID
, 0, 0, &msg
->hash
))
594 return (HCRYPTMSG
)msg
;
597 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
600 PCERT_INFO pCertInfo
;
601 HCRYPTPROV hCryptProv
;
603 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm
;
606 PCRYPT_ATTRIBUTE rgAuthAttr
;
608 PCRYPT_ATTRIBUTE rgUnauthAttr
;
610 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm
;
611 void *pvHashEncryptionAuxInfo
;
612 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS
;
614 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
618 PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners
;
620 PCERT_BLOB rgCertEncoded
;
622 PCRL_BLOB rgCrlEncoded
;
623 DWORD cAttrCertEncoded
;
624 PCERT_BLOB rgAttrCertEncoded
;
625 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS
;
627 static BOOL
CRYPT_IsValidSigner(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*signer
)
629 if (signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO
) &&
630 signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
632 SetLastError(E_INVALIDARG
);
635 if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
637 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
639 SetLastError(E_INVALIDARG
);
642 if (!signer
->pCertInfo
->Issuer
.cbData
)
644 SetLastError(E_INVALIDARG
);
648 else if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
650 switch (signer
->SignerId
.dwIdChoice
)
653 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
655 SetLastError(E_INVALIDARG
);
658 if (!signer
->pCertInfo
->Issuer
.cbData
)
660 SetLastError(E_INVALIDARG
);
664 case CERT_ID_ISSUER_SERIAL_NUMBER
:
665 if (!signer
->SignerId
.IssuerSerialNumber
.SerialNumber
.cbData
)
667 SetLastError(E_INVALIDARG
);
670 if (!signer
->SignerId
.IssuerSerialNumber
.Issuer
.cbData
)
672 SetLastError(E_INVALIDARG
);
676 case CERT_ID_KEY_IDENTIFIER
:
677 if (!signer
->SignerId
.KeyId
.cbData
)
679 SetLastError(E_INVALIDARG
);
684 SetLastError(E_INVALIDARG
);
686 if (signer
->HashEncryptionAlgorithm
.pszObjId
)
688 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
692 if (!signer
->hCryptProv
)
694 SetLastError(E_INVALIDARG
);
697 if (!CertOIDToAlgId(signer
->HashAlgorithm
.pszObjId
))
699 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
705 static BOOL
CRYPT_ConstructBlob(CRYPT_DATA_BLOB
*out
, const CRYPT_DATA_BLOB
*in
)
709 out
->cbData
= in
->cbData
;
712 out
->pbData
= CryptMemAlloc(out
->cbData
);
714 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
723 typedef struct _BlobArray
726 PCRYPT_DATA_BLOB blobs
;
729 static BOOL
CRYPT_ConstructBlobArray(BlobArray
*out
, const BlobArray
*in
)
733 out
->cBlobs
= in
->cBlobs
;
736 out
->blobs
= CryptMemAlloc(out
->cBlobs
* sizeof(CRYPT_DATA_BLOB
));
741 memset(out
->blobs
, 0, out
->cBlobs
* sizeof(CRYPT_DATA_BLOB
));
742 for (i
= 0; ret
&& i
< out
->cBlobs
; i
++)
743 ret
= CRYPT_ConstructBlob(&out
->blobs
[i
], &in
->blobs
[i
]);
751 static void CRYPT_FreeBlobArray(BlobArray
*array
)
755 for (i
= 0; i
< array
->cBlobs
; i
++)
756 CryptMemFree(array
->blobs
[i
].pbData
);
757 CryptMemFree(array
->blobs
);
760 static BOOL
CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE
*out
,
761 const CRYPT_ATTRIBUTE
*in
)
765 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
768 strcpy(out
->pszObjId
, in
->pszObjId
);
769 ret
= CRYPT_ConstructBlobArray((BlobArray
*)&out
->cValue
,
770 (const BlobArray
*)&in
->cValue
);
777 static BOOL
CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES
*out
,
778 const CRYPT_ATTRIBUTES
*in
)
782 out
->cAttr
= in
->cAttr
;
785 out
->rgAttr
= CryptMemAlloc(out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
790 memset(out
->rgAttr
, 0, out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
791 for (i
= 0; ret
&& i
< out
->cAttr
; i
++)
792 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[i
], &in
->rgAttr
[i
]);
802 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
803 static BOOL
CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO
*info
,
804 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*in
)
808 if (in
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
810 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
811 ret
= CRYPT_ConstructBlob(&info
->SignerId
.IssuerSerialNumber
.Issuer
,
812 &in
->pCertInfo
->Issuer
);
814 ret
= CRYPT_ConstructBlob(
815 &info
->SignerId
.IssuerSerialNumber
.SerialNumber
,
816 &in
->pCertInfo
->SerialNumber
);
817 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
821 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS).
822 * See CRYPT_IsValidSigner.
824 if (!in
->SignerId
.dwIdChoice
)
826 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
827 ret
= CRYPT_ConstructBlob(&info
->SignerId
.IssuerSerialNumber
.Issuer
,
828 &in
->pCertInfo
->Issuer
);
830 ret
= CRYPT_ConstructBlob(
831 &info
->SignerId
.IssuerSerialNumber
.SerialNumber
,
832 &in
->pCertInfo
->SerialNumber
);
833 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
835 else if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
837 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
838 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
839 ret
= CRYPT_ConstructBlob(&info
->SignerId
.IssuerSerialNumber
.Issuer
,
840 &in
->SignerId
.IssuerSerialNumber
.Issuer
);
842 ret
= CRYPT_ConstructBlob(
843 &info
->SignerId
.IssuerSerialNumber
.SerialNumber
,
844 &in
->SignerId
.IssuerSerialNumber
.SerialNumber
);
848 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */
849 info
->dwVersion
= CMSG_SIGNER_INFO_V3
;
850 info
->SignerId
.dwIdChoice
= CERT_ID_KEY_IDENTIFIER
;
851 ret
= CRYPT_ConstructBlob(&info
->SignerId
.KeyId
,
852 &in
->SignerId
.KeyId
);
855 /* Assumption: algorithm IDs will point to static strings, not
856 * stack-based ones, so copying the pointer values is safe.
858 info
->HashAlgorithm
.pszObjId
= in
->HashAlgorithm
.pszObjId
;
860 ret
= CRYPT_ConstructBlob(&info
->HashAlgorithm
.Parameters
,
861 &in
->HashAlgorithm
.Parameters
);
862 memset(&info
->HashEncryptionAlgorithm
, 0,
863 sizeof(info
->HashEncryptionAlgorithm
));
865 ret
= CRYPT_ConstructAttributes(&info
->AuthAttrs
,
866 (CRYPT_ATTRIBUTES
*)&in
->cAuthAttr
);
868 ret
= CRYPT_ConstructAttributes(&info
->UnauthAttrs
,
869 (CRYPT_ATTRIBUTES
*)&in
->cUnauthAttr
);
873 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO
*info
)
877 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
879 CryptMemFree(info
->SignerId
.IssuerSerialNumber
.Issuer
.pbData
);
880 CryptMemFree(info
->SignerId
.IssuerSerialNumber
.SerialNumber
.pbData
);
883 CryptMemFree(info
->SignerId
.KeyId
.pbData
);
884 CryptMemFree(info
->HashAlgorithm
.Parameters
.pbData
);
885 CryptMemFree(info
->EncryptedHash
.pbData
);
886 for (i
= 0; i
< info
->AuthAttrs
.cAttr
; i
++)
888 for (j
= 0; j
< info
->AuthAttrs
.rgAttr
[i
].cValue
; j
++)
889 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
890 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
);
891 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].pszObjId
);
893 CryptMemFree(info
->AuthAttrs
.rgAttr
);
894 for (i
= 0; i
< info
->UnauthAttrs
.cAttr
; i
++)
896 for (j
= 0; j
< info
->UnauthAttrs
.rgAttr
[i
].cValue
; j
++)
897 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
898 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
);
899 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].pszObjId
);
901 CryptMemFree(info
->UnauthAttrs
.rgAttr
);
904 typedef struct _CSignerHandles
906 HCRYPTHASH contentHash
;
907 HCRYPTHASH authAttrHash
;
910 typedef struct _CSignedMsgData
912 CRYPT_SIGNED_INFO
*info
;
914 CSignerHandles
*signerHandles
;
917 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
918 * Assumes signerIndex is a valid idnex, and that msg_data's info has already
921 static BOOL
CSignedMsgData_ConstructSignerHandles(CSignedMsgData
*msg_data
,
922 DWORD signerIndex
, HCRYPTPROV crypt_prov
)
927 algID
= CertOIDToAlgId(
928 msg_data
->info
->rgSignerInfo
[signerIndex
].HashAlgorithm
.pszObjId
);
929 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
930 &msg_data
->signerHandles
->contentHash
);
931 if (ret
&& msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
> 0)
932 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
933 &msg_data
->signerHandles
->authAttrHash
);
937 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
940 static BOOL
CSignedMsgData_AllocateHandles(CSignedMsgData
*msg_data
)
944 if (msg_data
->info
->cSignerInfo
)
946 msg_data
->signerHandles
=
947 CryptMemAlloc(msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
948 if (msg_data
->signerHandles
)
950 msg_data
->cSignerHandle
= msg_data
->info
->cSignerInfo
;
951 memset(msg_data
->signerHandles
, 0,
952 msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
956 msg_data
->cSignerHandle
= 0;
962 msg_data
->cSignerHandle
= 0;
963 msg_data
->signerHandles
= NULL
;
968 static void CSignedMsgData_CloseHandles(CSignedMsgData
*msg_data
)
972 for (i
= 0; i
< msg_data
->cSignerHandle
; i
++)
974 if (msg_data
->signerHandles
[i
].contentHash
)
975 CryptDestroyHash(msg_data
->signerHandles
[i
].contentHash
);
976 if (msg_data
->signerHandles
[i
].authAttrHash
)
977 CryptDestroyHash(msg_data
->signerHandles
[i
].authAttrHash
);
979 CryptMemFree(msg_data
->signerHandles
);
980 msg_data
->signerHandles
= NULL
;
981 msg_data
->cSignerHandle
= 0;
984 static BOOL
CSignedMsgData_UpdateHash(CSignedMsgData
*msg_data
,
985 const BYTE
*pbData
, DWORD cbData
)
990 for (i
= 0; ret
&& i
< msg_data
->cSignerHandle
; i
++)
991 ret
= CryptHashData(msg_data
->signerHandles
[i
].contentHash
, pbData
,
996 static BOOL
CRYPT_AppendAttribute(CRYPT_ATTRIBUTES
*out
,
997 const CRYPT_ATTRIBUTE
*in
)
1001 out
->rgAttr
= CryptMemRealloc(out
->rgAttr
,
1002 (out
->cAttr
+ 1) * sizeof(CRYPT_ATTRIBUTE
));
1005 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[out
->cAttr
], in
);
1012 static BOOL
CSignedMsgData_AppendMessageDigestAttribute(
1013 CSignedMsgData
*msg_data
, DWORD signerIndex
)
1017 CRYPT_HASH_BLOB hash
= { 0, NULL
}, encodedHash
= { 0, NULL
};
1018 char messageDigest
[] = szOID_RSA_messageDigest
;
1019 CRYPT_ATTRIBUTE messageDigestAttr
= { messageDigest
, 1, &encodedHash
};
1021 size
= sizeof(DWORD
);
1022 ret
= CryptGetHashParam(
1023 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHSIZE
,
1024 (LPBYTE
)&hash
.cbData
, &size
, 0);
1027 hash
.pbData
= CryptMemAlloc(hash
.cbData
);
1028 ret
= CryptGetHashParam(
1029 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHVAL
,
1030 hash
.pbData
, &hash
.cbData
, 0);
1033 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &hash
, CRYPT_ENCODE_ALLOC_FLAG
,
1034 NULL
, (LPBYTE
)&encodedHash
.pbData
, &encodedHash
.cbData
);
1037 ret
= CRYPT_AppendAttribute(
1038 &msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
,
1039 &messageDigestAttr
);
1040 LocalFree(encodedHash
.pbData
);
1043 CryptMemFree(hash
.pbData
);
1053 static BOOL
CSignedMsgData_UpdateAuthenticatedAttributes(
1054 CSignedMsgData
*msg_data
, SignOrVerify flag
)
1059 TRACE("(%p)\n", msg_data
);
1061 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1063 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1067 BYTE oid_rsa_data_encoded
[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
1068 0xf7,0x0d,0x01,0x07,0x01 };
1069 CRYPT_DATA_BLOB content
= { sizeof(oid_rsa_data_encoded
),
1070 oid_rsa_data_encoded
};
1071 char contentType
[] = szOID_RSA_contentType
;
1072 CRYPT_ATTRIBUTE contentTypeAttr
= { contentType
, 1, &content
};
1074 /* FIXME: does this depend on inner OID? */
1075 ret
= CRYPT_AppendAttribute(
1076 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
, &contentTypeAttr
);
1078 ret
= CSignedMsgData_AppendMessageDigestAttribute(msg_data
,
1083 LPBYTE encodedAttrs
;
1086 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, PKCS_ATTRIBUTES
,
1087 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
,
1088 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&encodedAttrs
, &size
);
1091 ret
= CryptHashData(
1092 msg_data
->signerHandles
[i
].authAttrHash
, encodedAttrs
,
1094 LocalFree(encodedAttrs
);
1099 TRACE("returning %d\n", ret
);
1103 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB
*hash
)
1108 for (i
= 0; i
< hash
->cbData
/ 2; i
++)
1110 tmp
= hash
->pbData
[hash
->cbData
- i
- 1];
1111 hash
->pbData
[hash
->cbData
- i
- 1] = hash
->pbData
[i
];
1112 hash
->pbData
[i
] = tmp
;
1116 static BOOL
CSignedMsgData_Sign(CSignedMsgData
*msg_data
)
1121 TRACE("(%p)\n", msg_data
);
1123 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1127 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1128 hash
= msg_data
->signerHandles
[i
].authAttrHash
;
1130 hash
= msg_data
->signerHandles
[i
].contentHash
;
1131 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0, NULL
,
1132 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1135 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
=
1137 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1138 if (msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
)
1140 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0,
1141 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
,
1142 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1145 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
);
1154 static BOOL
CSignedMsgData_Update(CSignedMsgData
*msg_data
,
1155 const BYTE
*pbData
, DWORD cbData
, BOOL fFinal
, SignOrVerify flag
)
1157 BOOL ret
= CSignedMsgData_UpdateHash(msg_data
, pbData
, cbData
);
1161 ret
= CSignedMsgData_UpdateAuthenticatedAttributes(msg_data
, flag
);
1162 if (ret
&& flag
== Sign
)
1163 ret
= CSignedMsgData_Sign(msg_data
);
1168 typedef struct _CSignedEncodeMsg
1171 CRYPT_DATA_BLOB data
;
1172 CSignedMsgData msg_data
;
1175 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1177 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1180 CryptMemFree(msg
->data
.pbData
);
1181 CRYPT_FreeBlobArray((BlobArray
*)&msg
->msg_data
.info
->cCertEncoded
);
1182 CRYPT_FreeBlobArray((BlobArray
*)&msg
->msg_data
.info
->cCrlEncoded
);
1183 for (i
= 0; i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1184 CSignerInfo_Free(&msg
->msg_data
.info
->rgSignerInfo
[i
]);
1185 CSignedMsgData_CloseHandles(&msg
->msg_data
);
1186 CryptMemFree(msg
->msg_data
.info
->rgSignerInfo
);
1187 CryptMemFree(msg
->msg_data
.info
);
1190 static BOOL
CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1191 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1193 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1196 switch (dwParamType
)
1198 case CMSG_CONTENT_PARAM
:
1200 CRYPT_CONTENT_INFO info
;
1202 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1203 &info
.Content
.cbData
);
1206 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1207 if (info
.Content
.pbData
)
1209 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1210 info
.Content
.pbData
, &info
.Content
.cbData
);
1213 char oid_rsa_signed
[] = szOID_RSA_signedData
;
1215 info
.pszObjId
= oid_rsa_signed
;
1216 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1217 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1219 CryptMemFree(info
.Content
.pbData
);
1226 case CMSG_BARE_CONTENT_PARAM
:
1228 CRYPT_SIGNED_INFO info
;
1229 char oid_rsa_data
[] = szOID_RSA_data
;
1231 info
= *msg
->msg_data
.info
;
1232 /* Quirk: OID is only encoded messages if an update has happened */
1233 if (msg
->base
.state
!= MsgStateInit
)
1234 info
.content
.pszObjId
= oid_rsa_data
;
1236 info
.content
.pszObjId
= NULL
;
1237 if (msg
->data
.cbData
)
1239 CRYPT_DATA_BLOB blob
= { msg
->data
.cbData
, msg
->data
.pbData
};
1241 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1242 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
1243 &info
.content
.Content
.pbData
, &info
.content
.Content
.cbData
);
1247 info
.content
.Content
.cbData
= 0;
1248 info
.content
.Content
.pbData
= NULL
;
1253 ret
= CRYPT_AsnEncodeCMSSignedInfo(&info
, pvData
, pcbData
);
1254 LocalFree(info
.content
.Content
.pbData
);
1258 case CMSG_COMPUTED_HASH_PARAM
:
1259 if (dwIndex
>= msg
->msg_data
.cSignerHandle
)
1260 SetLastError(CRYPT_E_INVALID_INDEX
);
1262 ret
= CryptGetHashParam(
1263 msg
->msg_data
.signerHandles
[dwIndex
].contentHash
, HP_HASHVAL
,
1264 pvData
, pcbData
, 0);
1266 case CMSG_ENCODED_SIGNER
:
1267 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1268 SetLastError(CRYPT_E_INVALID_INDEX
);
1270 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1271 CMS_SIGNER_INFO
, &msg
->msg_data
.info
->rgSignerInfo
[dwIndex
], 0,
1272 NULL
, pvData
, pcbData
);
1274 case CMSG_VERSION_PARAM
:
1275 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->msg_data
.info
->version
,
1276 sizeof(msg
->msg_data
.info
->version
));
1279 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1284 static BOOL
CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1285 DWORD cbData
, BOOL fFinal
)
1287 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1290 if (msg
->base
.state
== MsgStateFinalized
)
1291 SetLastError(CRYPT_E_MSG_ERROR
);
1292 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1294 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
, fFinal
,
1296 if (msg
->base
.streamed
)
1297 FIXME("streamed partial stub\n");
1298 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1303 SetLastError(CRYPT_E_MSG_ERROR
);
1308 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1309 if (msg
->data
.pbData
)
1311 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1312 msg
->data
.cbData
= cbData
;
1319 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
,
1321 msg
->base
.state
= MsgStateFinalized
;
1327 static HCRYPTMSG
CSignedEncodeMsg_Open(DWORD dwFlags
,
1328 const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
1329 PCMSG_STREAM_INFO pStreamInfo
)
1331 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*info
=
1332 (const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*)pvMsgEncodeInfo
;
1334 CSignedEncodeMsg
*msg
;
1336 if (info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO
) &&
1337 info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1339 SetLastError(E_INVALIDARG
);
1342 if (info
->cbSize
== sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
) &&
1343 info
->rgAttrCertEncoded
)
1345 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1348 for (i
= 0; i
< info
->cSigners
; i
++)
1349 if (!CRYPT_IsValidSigner(&info
->rgSigners
[i
]))
1351 msg
= CryptMemAlloc(sizeof(CSignedEncodeMsg
));
1356 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1357 CSignedEncodeMsg_Close
, CSignedEncodeMsg_GetParam
,
1358 CSignedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1359 msg
->data
.cbData
= 0;
1360 msg
->data
.pbData
= NULL
;
1361 msg
->msg_data
.info
= CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO
));
1362 if (msg
->msg_data
.info
)
1364 memset(msg
->msg_data
.info
, 0, sizeof(CRYPT_SIGNED_INFO
));
1365 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V1
;
1373 msg
->msg_data
.info
->rgSignerInfo
=
1374 CryptMemAlloc(info
->cSigners
* sizeof(CMSG_CMS_SIGNER_INFO
));
1375 if (msg
->msg_data
.info
->rgSignerInfo
)
1377 msg
->msg_data
.info
->cSignerInfo
= info
->cSigners
;
1378 memset(msg
->msg_data
.info
->rgSignerInfo
, 0,
1379 msg
->msg_data
.info
->cSignerInfo
*
1380 sizeof(CMSG_CMS_SIGNER_INFO
));
1381 ret
= CSignedMsgData_AllocateHandles(&msg
->msg_data
);
1382 for (i
= 0; ret
&& i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1384 if (info
->rgSigners
[i
].SignerId
.dwIdChoice
==
1385 CERT_ID_KEY_IDENTIFIER
)
1386 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V3
;
1387 ret
= CSignerInfo_Construct(
1388 &msg
->msg_data
.info
->rgSignerInfo
[i
],
1389 &info
->rgSigners
[i
]);
1392 ret
= CSignedMsgData_ConstructSignerHandles(
1393 &msg
->msg_data
, i
, info
->rgSigners
[i
].hCryptProv
);
1394 if (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1395 CryptReleaseContext(info
->rgSigners
[i
].hCryptProv
,
1405 msg
->msg_data
.info
->cSignerInfo
= 0;
1406 msg
->msg_data
.signerHandles
= NULL
;
1407 msg
->msg_data
.cSignerHandle
= 0;
1411 ret
= CRYPT_ConstructBlobArray(
1412 (BlobArray
*)&msg
->msg_data
.info
->cCertEncoded
,
1413 (const BlobArray
*)&info
->cCertEncoded
);
1415 ret
= CRYPT_ConstructBlobArray(
1416 (BlobArray
*)&msg
->msg_data
.info
->cCrlEncoded
,
1417 (const BlobArray
*)&info
->cCrlEncoded
);
1420 CSignedEncodeMsg_Close(msg
);
1427 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
1428 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
1429 PCMSG_STREAM_INFO pStreamInfo
)
1431 HCRYPTMSG msg
= NULL
;
1433 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
1434 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
1436 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
1438 SetLastError(E_INVALIDARG
);
1444 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1445 pszInnerContentObjID
, pStreamInfo
);
1448 msg
= CHashEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1449 pszInnerContentObjID
, pStreamInfo
);
1452 msg
= CSignedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1453 pszInnerContentObjID
, pStreamInfo
);
1455 case CMSG_ENVELOPED
:
1456 FIXME("unimplemented for type CMSG_ENVELOPED\n");
1458 case CMSG_SIGNED_AND_ENVELOPED
:
1459 case CMSG_ENCRYPTED
:
1460 /* defined but invalid, fall through */
1462 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1467 typedef struct _CDecodeMsg
1471 HCRYPTPROV crypt_prov
;
1474 CSignedMsgData signed_data
;
1476 CRYPT_DATA_BLOB msg_data
;
1477 CRYPT_DATA_BLOB detached_data
;
1478 PCONTEXT_PROPERTY_LIST properties
;
1481 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg
)
1483 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
1485 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1486 CryptReleaseContext(msg
->crypt_prov
, 0);
1491 CryptDestroyHash(msg
->u
.hash
);
1494 if (msg
->u
.signed_data
.info
)
1496 LocalFree(msg
->u
.signed_data
.info
);
1497 CSignedMsgData_CloseHandles(&msg
->u
.signed_data
);
1501 CryptMemFree(msg
->msg_data
.pbData
);
1502 CryptMemFree(msg
->detached_data
.pbData
);
1503 ContextPropertyList_Free(msg
->properties
);
1506 static BOOL
CDecodeMsg_CopyData(CRYPT_DATA_BLOB
*blob
, const BYTE
*pbData
,
1514 blob
->pbData
= CryptMemRealloc(blob
->pbData
,
1515 blob
->cbData
+ cbData
);
1517 blob
->pbData
= CryptMemAlloc(cbData
);
1520 memcpy(blob
->pbData
+ blob
->cbData
, pbData
, cbData
);
1521 blob
->cbData
+= cbData
;
1529 static BOOL
CDecodeMsg_DecodeDataContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
1532 CRYPT_DATA_BLOB
*data
;
1535 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1536 blob
->pbData
, blob
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&data
,
1540 ret
= ContextPropertyList_SetProperty(msg
->properties
,
1541 CMSG_CONTENT_PARAM
, data
->pbData
, data
->cbData
);
1547 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg
*msg
, DWORD param
,
1548 const CRYPT_ALGORITHM_IDENTIFIER
*id
)
1550 static const BYTE nullParams
[] = { ASN_NULL
, 0 };
1551 CRYPT_ALGORITHM_IDENTIFIER
*copy
;
1552 DWORD len
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
1554 /* Linearize algorithm id */
1555 len
+= strlen(id
->pszObjId
) + 1;
1556 len
+= id
->Parameters
.cbData
;
1557 copy
= CryptMemAlloc(len
);
1561 (LPSTR
)((BYTE
*)copy
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
1562 strcpy(copy
->pszObjId
, id
->pszObjId
);
1563 copy
->Parameters
.pbData
= (BYTE
*)copy
->pszObjId
+ strlen(id
->pszObjId
)
1565 /* Trick: omit NULL parameters */
1566 if (id
->Parameters
.cbData
== sizeof(nullParams
) &&
1567 !memcmp(id
->Parameters
.pbData
, nullParams
, sizeof(nullParams
)))
1569 copy
->Parameters
.cbData
= 0;
1570 len
-= sizeof(nullParams
);
1573 copy
->Parameters
.cbData
= id
->Parameters
.cbData
;
1574 if (copy
->Parameters
.cbData
)
1575 memcpy(copy
->Parameters
.pbData
, id
->Parameters
.pbData
,
1576 id
->Parameters
.cbData
);
1577 ContextPropertyList_SetProperty(msg
->properties
, param
, (BYTE
*)copy
,
1583 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER
*id
)
1585 id
->pszObjId
= (LPSTR
)((BYTE
*)id
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
1586 id
->Parameters
.pbData
= (BYTE
*)id
->pszObjId
+ strlen(id
->pszObjId
) + 1;
1589 static BOOL
CDecodeMsg_DecodeHashedContent(CDecodeMsg
*msg
,
1590 CRYPT_DER_BLOB
*blob
)
1593 CRYPT_DIGESTED_DATA
*digestedData
;
1596 ret
= CRYPT_AsnDecodePKCSDigestedData(blob
->pbData
, blob
->cbData
,
1597 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_DIGESTED_DATA
*)&digestedData
,
1601 ContextPropertyList_SetProperty(msg
->properties
, CMSG_VERSION_PARAM
,
1602 (const BYTE
*)&digestedData
->version
, sizeof(digestedData
->version
));
1603 CDecodeMsg_SaveAlgorithmID(msg
, CMSG_HASH_ALGORITHM_PARAM
,
1604 &digestedData
->DigestAlgorithm
);
1605 ContextPropertyList_SetProperty(msg
->properties
,
1606 CMSG_INNER_CONTENT_TYPE_PARAM
,
1607 (const BYTE
*)digestedData
->ContentInfo
.pszObjId
,
1608 digestedData
->ContentInfo
.pszObjId
?
1609 strlen(digestedData
->ContentInfo
.pszObjId
) + 1 : 0);
1610 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1612 if (digestedData
->ContentInfo
.Content
.cbData
)
1613 CDecodeMsg_DecodeDataContent(msg
,
1614 &digestedData
->ContentInfo
.Content
);
1616 ContextPropertyList_SetProperty(msg
->properties
,
1617 CMSG_CONTENT_PARAM
, NULL
, 0);
1619 ContextPropertyList_SetProperty(msg
->properties
, CMSG_HASH_DATA_PARAM
,
1620 digestedData
->hash
.pbData
, digestedData
->hash
.cbData
);
1621 LocalFree(digestedData
);
1626 static BOOL
CDecodeMsg_DecodeSignedContent(CDecodeMsg
*msg
,
1627 CRYPT_DER_BLOB
*blob
)
1630 CRYPT_SIGNED_INFO
*signedInfo
;
1633 ret
= CRYPT_AsnDecodeCMSSignedInfo(blob
->pbData
, blob
->cbData
,
1634 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_SIGNED_INFO
*)&signedInfo
,
1637 msg
->u
.signed_data
.info
= signedInfo
;
1641 /* Decodes the content in blob as the type given, and updates the value
1642 * (type, parameters, etc.) of msg based on what blob contains.
1643 * It doesn't just use msg's type, to allow a recursive call from an implicitly
1644 * typed message once the outer content info has been decoded.
1646 static BOOL
CDecodeMsg_DecodeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
,
1654 if ((ret
= CDecodeMsg_DecodeDataContent(msg
, blob
)))
1655 msg
->type
= CMSG_DATA
;
1658 if ((ret
= CDecodeMsg_DecodeHashedContent(msg
, blob
)))
1659 msg
->type
= CMSG_HASHED
;
1661 case CMSG_ENVELOPED
:
1662 FIXME("unimplemented for type CMSG_ENVELOPED\n");
1666 if ((ret
= CDecodeMsg_DecodeSignedContent(msg
, blob
)))
1667 msg
->type
= CMSG_SIGNED
;
1671 CRYPT_CONTENT_INFO
*info
;
1674 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
,
1675 msg
->msg_data
.pbData
, msg
->msg_data
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
1676 NULL
, (LPBYTE
)&info
, &size
);
1679 if (!strcmp(info
->pszObjId
, szOID_RSA_data
))
1680 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
, CMSG_DATA
);
1681 else if (!strcmp(info
->pszObjId
, szOID_RSA_digestedData
))
1682 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1684 else if (!strcmp(info
->pszObjId
, szOID_RSA_envelopedData
))
1685 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1687 else if (!strcmp(info
->pszObjId
, szOID_RSA_signedData
))
1688 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1692 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1702 static BOOL
CDecodeMsg_FinalizeHashedContent(CDecodeMsg
*msg
,
1703 CRYPT_DER_BLOB
*blob
)
1705 CRYPT_ALGORITHM_IDENTIFIER
*hashAlgoID
= NULL
;
1710 CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, NULL
, &size
);
1711 hashAlgoID
= CryptMemAlloc(size
);
1712 ret
= CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, hashAlgoID
,
1715 algID
= CertOIDToAlgId(hashAlgoID
->pszObjId
);
1716 ret
= CryptCreateHash(msg
->crypt_prov
, algID
, 0, 0, &msg
->u
.hash
);
1719 CRYPT_DATA_BLOB content
;
1721 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1723 /* Unlike for non-detached messages, the data were never stored as
1724 * the content param, but were saved in msg->detached_data instead.
1725 * Set the content property with the detached data so the data may
1728 ContextPropertyList_SetProperty(msg
->properties
,
1729 CMSG_CONTENT_PARAM
, msg
->detached_data
.pbData
,
1730 msg
->detached_data
.cbData
);
1732 ret
= ContextPropertyList_FindProperty(msg
->properties
,
1733 CMSG_CONTENT_PARAM
, &content
);
1735 ret
= CryptHashData(msg
->u
.hash
, content
.pbData
, content
.cbData
, 0);
1737 CryptMemFree(hashAlgoID
);
1741 static BOOL
CDecodeMsg_FinalizeSignedContent(CDecodeMsg
*msg
,
1742 CRYPT_DER_BLOB
*blob
)
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
,
1753 CRYPT_DATA_BLOB
*content
;
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
1760 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1761 content
= &msg
->detached_data
;
1763 content
= &msg
->u
.signed_data
.info
->content
.Content
;
1764 if (content
->cbData
)
1766 /* If the message is not detached, have to decode the message's
1767 * content if the type is szOID_RSA_data.
1769 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) &&
1770 !strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
1773 CRYPT_DATA_BLOB
*blob
;
1775 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
,
1776 X509_OCTET_STRING
, content
->pbData
, content
->cbData
,
1777 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&blob
, &size
);
1780 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
1781 blob
->pbData
, blob
->cbData
, TRUE
, Verify
);
1786 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
1787 content
->pbData
, content
->cbData
, TRUE
, Verify
);
1793 static BOOL
CDecodeMsg_FinalizeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
1800 ret
= CDecodeMsg_FinalizeHashedContent(msg
, blob
);
1803 ret
= CDecodeMsg_FinalizeSignedContent(msg
, blob
);
1811 static BOOL
CDecodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1812 DWORD cbData
, BOOL fFinal
)
1814 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
1817 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
1819 if (msg
->base
.state
== MsgStateFinalized
)
1820 SetLastError(CRYPT_E_MSG_ERROR
);
1821 else if (msg
->base
.streamed
)
1823 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg
, pbData
,
1825 switch (msg
->base
.state
)
1828 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
1831 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1832 msg
->base
.state
= MsgStateDataFinalized
;
1834 msg
->base
.state
= MsgStateFinalized
;
1837 msg
->base
.state
= MsgStateUpdated
;
1839 case MsgStateUpdated
:
1840 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
1843 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1844 msg
->base
.state
= MsgStateDataFinalized
;
1846 msg
->base
.state
= MsgStateFinalized
;
1849 case MsgStateDataFinalized
:
1850 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
1852 msg
->base
.state
= MsgStateFinalized
;
1855 SetLastError(CRYPT_E_MSG_ERROR
);
1862 SetLastError(CRYPT_E_MSG_ERROR
);
1865 switch (msg
->base
.state
)
1868 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
1869 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1870 msg
->base
.state
= MsgStateDataFinalized
;
1872 msg
->base
.state
= MsgStateFinalized
;
1874 case MsgStateDataFinalized
:
1875 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
1876 msg
->base
.state
= MsgStateFinalized
;
1879 SetLastError(CRYPT_E_MSG_ERROR
);
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
);
1894 static BOOL
CDecodeHashMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
1895 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1899 switch (dwParamType
)
1901 case CMSG_TYPE_PARAM
:
1902 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
1904 case CMSG_HASH_ALGORITHM_PARAM
:
1906 CRYPT_DATA_BLOB blob
;
1908 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
1912 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
1914 CRYPT_FixUpAlgorithmID((CRYPT_ALGORITHM_IDENTIFIER
*)pvData
);
1917 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1920 case CMSG_COMPUTED_HASH_PARAM
:
1921 ret
= CryptGetHashParam(msg
->u
.hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
1925 CRYPT_DATA_BLOB blob
;
1927 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
1930 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
1932 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
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.
1942 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB
*out
,
1943 const CRYPT_DATA_BLOB
*in
, LPBYTE
*nextData
)
1945 out
->cbData
= in
->cbData
;
1948 out
->pbData
= *nextData
;
1949 memcpy(out
->pbData
, in
->pbData
, in
->cbData
);
1950 *nextData
+= in
->cbData
;
1954 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
1955 const CRYPT_ALGORITHM_IDENTIFIER
*in
, LPBYTE
*nextData
)
1959 out
->pszObjId
= (LPSTR
)*nextData
;
1960 strcpy(out
->pszObjId
, in
->pszObjId
);
1961 *nextData
+= strlen(out
->pszObjId
) + 1;
1963 CRYPT_CopyBlob(&out
->Parameters
, &in
->Parameters
, nextData
);
1966 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES
*out
,
1967 const CRYPT_ATTRIBUTES
*in
, LPBYTE
*nextData
)
1969 out
->cAttr
= in
->cAttr
;
1974 if ((*nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
))
1975 *nextData
+= (*nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
);
1976 out
->rgAttr
= (CRYPT_ATTRIBUTE
*)*nextData
;
1977 *nextData
+= in
->cAttr
* sizeof(CRYPT_ATTRIBUTE
);
1978 for (i
= 0; i
< in
->cAttr
; i
++)
1980 if (in
->rgAttr
[i
].pszObjId
)
1982 out
->rgAttr
[i
].pszObjId
= (LPSTR
)*nextData
;
1983 strcpy(out
->rgAttr
[i
].pszObjId
, in
->rgAttr
[i
].pszObjId
);
1984 *nextData
+= strlen(in
->rgAttr
[i
].pszObjId
) + 1;
1986 if (in
->rgAttr
[i
].cValue
)
1990 out
->rgAttr
[i
].cValue
= in
->rgAttr
[i
].cValue
;
1991 if ((*nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
))
1992 *nextData
+= (*nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
);
1993 out
->rgAttr
[i
].rgValue
= (PCRYPT_DATA_BLOB
)*nextData
;
1994 *nextData
+= in
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
1995 for (j
= 0; j
< in
->rgAttr
[i
].cValue
; j
++)
1996 CRYPT_CopyBlob(&out
->rgAttr
[i
].rgValue
[j
],
1997 &in
->rgAttr
[i
].rgValue
[j
], nextData
);
2003 static DWORD
CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES
*attr
)
2005 DWORD size
= attr
->cAttr
* sizeof(CRYPT_ATTRIBUTE
), i
, j
;
2007 for (i
= 0; i
< attr
->cAttr
; i
++)
2009 if (attr
->rgAttr
[i
].pszObjId
)
2010 size
+= strlen(attr
->rgAttr
[i
].pszObjId
) + 1;
2012 if (size
% sizeof(DWORD_PTR
))
2013 size
+= size
% sizeof(DWORD_PTR
);
2014 size
+= attr
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2015 for (j
= 0; j
< attr
->rgAttr
[i
].cValue
; j
++)
2016 size
+= attr
->rgAttr
[i
].rgValue
[j
].cbData
;
2018 /* align pointer again to be conservative */
2019 if (size
% sizeof(DWORD_PTR
))
2020 size
+= size
% sizeof(DWORD_PTR
);
2024 static DWORD
CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB
*keyId
)
2026 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2029 CERT_RDN rdn
= { 1, &attr
};
2030 CERT_NAME_INFO name
= { 1, &rdn
};
2032 attr
.pszObjId
= oid_key_rdn
;
2033 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2034 attr
.Value
.cbData
= keyId
->cbData
;
2035 attr
.Value
.pbData
= keyId
->pbData
;
2036 if (CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, NULL
, &size
))
2037 size
++; /* Only include size of special zero serial number on success */
2041 static BOOL
CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB
*issuer
,
2042 CRYPT_INTEGER_BLOB
*serialNumber
, const CRYPT_DATA_BLOB
*keyId
, DWORD encodedLen
,
2045 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2047 CERT_RDN rdn
= { 1, &attr
};
2048 CERT_NAME_INFO name
= { 1, &rdn
};
2051 /* Encode special zero serial number */
2052 serialNumber
->cbData
= 1;
2053 serialNumber
->pbData
= *nextData
;
2057 issuer
->pbData
= *nextData
;
2058 attr
.pszObjId
= oid_key_rdn
;
2059 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2060 attr
.Value
.cbData
= keyId
->cbData
;
2061 attr
.Value
.pbData
= keyId
->pbData
;
2062 ret
= CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, *nextData
,
2066 *nextData
+= encodedLen
;
2067 issuer
->cbData
= encodedLen
;
2072 static BOOL
CRYPT_CopySignerInfo(void *pvData
, DWORD
*pcbData
,
2073 const CMSG_CMS_SIGNER_INFO
*in
)
2075 DWORD size
= sizeof(CMSG_SIGNER_INFO
), rdnSize
;
2078 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2080 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2082 size
+= in
->SignerId
.IssuerSerialNumber
.Issuer
.cbData
;
2083 size
+= in
->SignerId
.IssuerSerialNumber
.SerialNumber
.cbData
;
2087 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.KeyId
);
2090 if (in
->HashAlgorithm
.pszObjId
)
2091 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2092 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2093 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2094 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2095 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2096 size
+= in
->EncryptedHash
.cbData
;
2098 if (size
% sizeof(DWORD_PTR
))
2099 size
+= size
% sizeof(DWORD_PTR
);
2100 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2101 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2107 else if (*pcbData
< size
)
2110 SetLastError(ERROR_MORE_DATA
);
2115 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_SIGNER_INFO
);
2116 CMSG_SIGNER_INFO
*out
= (CMSG_SIGNER_INFO
*)pvData
;
2119 out
->dwVersion
= in
->dwVersion
;
2120 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2122 CRYPT_CopyBlob(&out
->Issuer
,
2123 &in
->SignerId
.IssuerSerialNumber
.Issuer
, &nextData
);
2124 CRYPT_CopyBlob(&out
->SerialNumber
,
2125 &in
->SignerId
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2128 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2129 &in
->SignerId
.KeyId
, rdnSize
, &nextData
);
2132 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2134 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2135 &in
->HashEncryptionAlgorithm
, &nextData
);
2136 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2138 if ((nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
))
2139 nextData
+= (nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
);
2140 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2141 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2144 TRACE("returning %d\n", ret
);
2148 static BOOL
CRYPT_CopyCMSSignerInfo(void *pvData
, DWORD
*pcbData
,
2149 const CMSG_CMS_SIGNER_INFO
*in
)
2151 DWORD size
= sizeof(CMSG_CMS_SIGNER_INFO
);
2154 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2156 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2158 size
+= in
->SignerId
.IssuerSerialNumber
.Issuer
.cbData
;
2159 size
+= in
->SignerId
.IssuerSerialNumber
.SerialNumber
.cbData
;
2162 size
+= in
->SignerId
.KeyId
.cbData
;
2163 if (in
->HashAlgorithm
.pszObjId
)
2164 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2165 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2166 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2167 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2168 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2169 size
+= in
->EncryptedHash
.cbData
;
2171 if (size
% sizeof(DWORD_PTR
))
2172 size
+= size
% sizeof(DWORD_PTR
);
2173 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2174 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2180 else if (*pcbData
< size
)
2183 SetLastError(ERROR_MORE_DATA
);
2188 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_CMS_SIGNER_INFO
);
2189 CMSG_CMS_SIGNER_INFO
*out
= (CMSG_CMS_SIGNER_INFO
*)pvData
;
2191 out
->dwVersion
= in
->dwVersion
;
2192 out
->SignerId
.dwIdChoice
= in
->SignerId
.dwIdChoice
;
2193 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2195 CRYPT_CopyBlob(&out
->SignerId
.IssuerSerialNumber
.Issuer
,
2196 &in
->SignerId
.IssuerSerialNumber
.Issuer
, &nextData
);
2197 CRYPT_CopyBlob(&out
->SignerId
.IssuerSerialNumber
.SerialNumber
,
2198 &in
->SignerId
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2201 CRYPT_CopyBlob(&out
->SignerId
.KeyId
, &in
->SignerId
.KeyId
, &nextData
);
2202 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2204 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2205 &in
->HashEncryptionAlgorithm
, &nextData
);
2206 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2208 if ((nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
))
2209 nextData
+= (nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
);
2210 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2211 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2214 TRACE("returning %d\n", ret
);
2218 static BOOL
CRYPT_CopySignerCertInfo(void *pvData
, DWORD
*pcbData
,
2219 const CMSG_CMS_SIGNER_INFO
*in
)
2221 DWORD size
= sizeof(CERT_INFO
), rdnSize
;
2224 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2226 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2228 size
+= in
->SignerId
.IssuerSerialNumber
.Issuer
.cbData
;
2229 size
+= in
->SignerId
.IssuerSerialNumber
.SerialNumber
.cbData
;
2233 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.KeyId
);
2241 else if (*pcbData
< size
)
2244 SetLastError(ERROR_MORE_DATA
);
2249 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2250 CERT_INFO
*out
= (CERT_INFO
*)pvData
;
2252 memset(out
, 0, sizeof(CERT_INFO
));
2253 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2255 CRYPT_CopyBlob(&out
->Issuer
,
2256 &in
->SignerId
.IssuerSerialNumber
.Issuer
, &nextData
);
2257 CRYPT_CopyBlob(&out
->SerialNumber
,
2258 &in
->SignerId
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2262 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2263 &in
->SignerId
.KeyId
, rdnSize
, &nextData
);
2265 TRACE("returning %d\n", ret
);
2269 static BOOL
CDecodeSignedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2270 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2274 switch (dwParamType
)
2276 case CMSG_TYPE_PARAM
:
2277 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2279 case CMSG_CONTENT_PARAM
:
2280 if (msg
->u
.signed_data
.info
)
2282 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2285 CRYPT_DATA_BLOB
*blob
;
2288 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
2289 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
2290 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
2291 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&blob
, &size
);
2294 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
->pbData
,
2300 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2301 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
2302 msg
->u
.signed_data
.info
->content
.Content
.cbData
);
2305 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2307 case CMSG_INNER_CONTENT_TYPE_PARAM
:
2308 if (msg
->u
.signed_data
.info
)
2309 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2310 msg
->u
.signed_data
.info
->content
.pszObjId
,
2311 strlen(msg
->u
.signed_data
.info
->content
.pszObjId
) + 1);
2313 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2315 case CMSG_SIGNER_COUNT_PARAM
:
2316 if (msg
->u
.signed_data
.info
)
2317 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2318 &msg
->u
.signed_data
.info
->cSignerInfo
, sizeof(DWORD
));
2320 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2322 case CMSG_SIGNER_INFO_PARAM
:
2323 if (msg
->u
.signed_data
.info
)
2325 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2326 SetLastError(CRYPT_E_INVALID_INDEX
);
2328 ret
= CRYPT_CopySignerInfo(pvData
, pcbData
,
2329 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
2332 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2334 case CMSG_SIGNER_CERT_INFO_PARAM
:
2335 if (msg
->u
.signed_data
.info
)
2337 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2338 SetLastError(CRYPT_E_INVALID_INDEX
);
2340 ret
= CRYPT_CopySignerCertInfo(pvData
, pcbData
,
2341 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
2344 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2346 case CMSG_CERT_COUNT_PARAM
:
2347 if (msg
->u
.signed_data
.info
)
2348 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2349 &msg
->u
.signed_data
.info
->cCertEncoded
, sizeof(DWORD
));
2351 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2353 case CMSG_CERT_PARAM
:
2354 if (msg
->u
.signed_data
.info
)
2356 if (dwIndex
>= msg
->u
.signed_data
.info
->cCertEncoded
)
2357 SetLastError(CRYPT_E_INVALID_INDEX
);
2359 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2360 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].pbData
,
2361 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].cbData
);
2364 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2366 case CMSG_CRL_COUNT_PARAM
:
2367 if (msg
->u
.signed_data
.info
)
2368 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2369 &msg
->u
.signed_data
.info
->cCrlEncoded
, sizeof(DWORD
));
2371 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2373 case CMSG_CRL_PARAM
:
2374 if (msg
->u
.signed_data
.info
)
2376 if (dwIndex
>= msg
->u
.signed_data
.info
->cCrlEncoded
)
2377 SetLastError(CRYPT_E_INVALID_INDEX
);
2379 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2380 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].pbData
,
2381 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].cbData
);
2384 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2386 case CMSG_COMPUTED_HASH_PARAM
:
2387 if (msg
->u
.signed_data
.info
)
2389 if (dwIndex
>= msg
->u
.signed_data
.cSignerHandle
)
2390 SetLastError(CRYPT_E_INVALID_INDEX
);
2392 ret
= CryptGetHashParam(
2393 msg
->u
.signed_data
.signerHandles
[dwIndex
].contentHash
,
2394 HP_HASHVAL
, pvData
, pcbData
, 0);
2397 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2399 case CMSG_ATTR_CERT_COUNT_PARAM
:
2400 if (msg
->u
.signed_data
.info
)
2402 DWORD attrCertCount
= 0;
2404 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2405 &attrCertCount
, sizeof(DWORD
));
2408 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2410 case CMSG_ATTR_CERT_PARAM
:
2411 if (msg
->u
.signed_data
.info
)
2412 SetLastError(CRYPT_E_INVALID_INDEX
);
2414 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2416 case CMSG_CMS_SIGNER_INFO_PARAM
:
2417 if (msg
->u
.signed_data
.info
)
2419 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2420 SetLastError(CRYPT_E_INVALID_INDEX
);
2422 ret
= CRYPT_CopyCMSSignerInfo(pvData
, pcbData
,
2423 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
2426 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2429 FIXME("unimplemented for %d\n", dwParamType
);
2430 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2435 static BOOL
CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
2436 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2438 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
2444 ret
= CDecodeHashMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2448 ret
= CDecodeSignedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2452 switch (dwParamType
)
2454 case CMSG_TYPE_PARAM
:
2455 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
,
2460 CRYPT_DATA_BLOB blob
;
2462 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2465 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
,
2468 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2475 static BOOL
CDecodeHashMsg_VerifyHash(CDecodeMsg
*msg
)
2478 CRYPT_DATA_BLOB hashBlob
;
2480 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2481 CMSG_HASH_DATA_PARAM
, &hashBlob
);
2484 DWORD computedHashSize
= 0;
2486 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
,
2488 if (hashBlob
.cbData
== computedHashSize
)
2490 LPBYTE computedHash
= CryptMemAlloc(computedHashSize
);
2494 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
2495 computedHash
, &computedHashSize
);
2498 if (memcmp(hashBlob
.pbData
, computedHash
, hashBlob
.cbData
))
2500 SetLastError(CRYPT_E_HASH_VALUE
);
2504 CryptMemFree(computedHash
);
2508 SetLastError(ERROR_OUTOFMEMORY
);
2514 SetLastError(CRYPT_E_HASH_VALUE
);
2521 static BOOL
CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg
*msg
,
2522 HCRYPTPROV prov
, DWORD signerIndex
, PCERT_PUBLIC_KEY_INFO keyInfo
)
2528 prov
= msg
->crypt_prov
;
2529 ret
= CryptImportPublicKeyInfo(prov
, X509_ASN_ENCODING
, keyInfo
, &key
);
2533 CRYPT_HASH_BLOB reversedHash
;
2535 if (msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
)
2536 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].authAttrHash
;
2538 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].contentHash
;
2539 ret
= CRYPT_ConstructBlob(&reversedHash
,
2540 &msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].EncryptedHash
);
2543 CRYPT_ReverseBytes(&reversedHash
);
2544 ret
= CryptVerifySignatureW(hash
, reversedHash
.pbData
,
2545 reversedHash
.cbData
, key
, NULL
, 0);
2546 CryptMemFree(reversedHash
.pbData
);
2548 CryptDestroyKey(key
);
2553 static BOOL
CDecodeSignedMsg_VerifySignature(CDecodeMsg
*msg
, PCERT_INFO info
)
2558 for (i
= 0; !ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
2560 PCMSG_CMS_SIGNER_INFO signerInfo
=
2561 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
];
2563 if (signerInfo
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2565 ret
= CertCompareCertificateName(X509_ASN_ENCODING
,
2566 &signerInfo
->SignerId
.IssuerSerialNumber
.Issuer
,
2570 ret
= CertCompareIntegerBlob(
2571 &signerInfo
->SignerId
.IssuerSerialNumber
.SerialNumber
,
2572 &info
->SerialNumber
);
2579 FIXME("signer %d: unimplemented for key id\n", i
);
2583 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, 0, i
,
2584 &info
->SubjectPublicKeyInfo
);
2586 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2591 static BOOL
CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg
*msg
,
2592 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para
)
2596 if (para
->cbSize
!= sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
))
2597 SetLastError(ERROR_INVALID_PARAMETER
);
2598 else if (para
->dwSignerIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2599 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2602 switch (para
->dwSignerType
)
2604 case CMSG_VERIFY_SIGNER_PUBKEY
:
2605 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
,
2606 para
->hCryptProv
, para
->dwSignerIndex
,
2607 (PCERT_PUBLIC_KEY_INFO
)para
->pvSigner
);
2609 case CMSG_VERIFY_SIGNER_CERT
:
2611 PCCERT_CONTEXT cert
= (PCCERT_CONTEXT
)para
->pvSigner
;
2613 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, para
->hCryptProv
,
2614 para
->dwSignerIndex
, &cert
->pCertInfo
->SubjectPublicKeyInfo
);
2618 FIXME("unimplemented for signer type %d\n", para
->dwSignerType
);
2619 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2625 static BOOL
CDecodeMsg_Control(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
2626 DWORD dwCtrlType
, const void *pvCtrlPara
)
2628 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
2633 case CMSG_CTRL_VERIFY_SIGNATURE
:
2637 ret
= CDecodeSignedMsg_VerifySignature(msg
, (PCERT_INFO
)pvCtrlPara
);
2640 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2643 case CMSG_CTRL_DECRYPT
:
2647 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2650 case CMSG_CTRL_VERIFY_HASH
:
2654 ret
= CDecodeHashMsg_VerifyHash(msg
);
2657 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2660 case CMSG_CTRL_VERIFY_SIGNATURE_EX
:
2664 ret
= CDecodeSignedMsg_VerifySignatureEx(msg
,
2665 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
)pvCtrlPara
);
2668 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2672 SetLastError(CRYPT_E_CONTROL_TYPE
);
2677 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
2678 DWORD dwMsgType
, HCRYPTPROV_LEGACY hCryptProv
, PCERT_INFO pRecipientInfo
,
2679 PCMSG_STREAM_INFO pStreamInfo
)
2683 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType
,
2684 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
2686 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
2688 SetLastError(E_INVALIDARG
);
2691 msg
= CryptMemAlloc(sizeof(CDecodeMsg
));
2694 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
2695 CDecodeMsg_Close
, CDecodeMsg_GetParam
, CDecodeMsg_Update
,
2696 CDecodeMsg_Control
);
2697 msg
->type
= dwMsgType
;
2699 msg
->crypt_prov
= hCryptProv
;
2702 msg
->crypt_prov
= CRYPT_GetDefaultProvider();
2703 msg
->base
.open_flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
2705 memset(&msg
->u
, 0, sizeof(msg
->u
));
2706 msg
->msg_data
.cbData
= 0;
2707 msg
->msg_data
.pbData
= NULL
;
2708 msg
->detached_data
.cbData
= 0;
2709 msg
->detached_data
.pbData
= NULL
;
2710 msg
->properties
= ContextPropertyList_Create();
2715 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
2717 TRACE("(%p)\n", hCryptMsg
);
2721 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2723 InterlockedIncrement(&msg
->ref
);
2728 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
2730 TRACE("(%p)\n", hCryptMsg
);
2734 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2736 if (InterlockedDecrement(&msg
->ref
) == 0)
2738 TRACE("freeing %p\n", msg
);
2747 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
2748 DWORD cbData
, BOOL fFinal
)
2750 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2752 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
2754 return msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
2757 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
2758 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2760 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2762 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
2764 return msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);
2767 BOOL WINAPI
CryptMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
2768 DWORD dwCtrlType
, const void *pvCtrlPara
)
2770 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2772 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
,
2774 return msg
->control(hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
2777 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
2778 DWORD dwSignerIndex
)
2780 CERT_INFO
*certInfo
= NULL
;
2783 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
2786 certInfo
= CryptMemAlloc(size
);
2789 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
2790 dwSignerIndex
, certInfo
, &size
))
2792 CryptMemFree(certInfo
);
2800 BOOL WINAPI
CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg
, DWORD cSignerStore
,
2801 HCERTSTORE
*rghSignerStore
, DWORD dwFlags
, PCCERT_CONTEXT
*ppSigner
,
2802 DWORD
*pdwSignerIndex
)
2805 DWORD i
, signerIndex
;
2806 PCCERT_CONTEXT signerCert
= NULL
;
2809 TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg
, cSignerStore
,
2810 rghSignerStore
, dwFlags
, ppSigner
, pdwSignerIndex
);
2812 /* Clear output parameters */
2815 if (pdwSignerIndex
&& !(dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
))
2816 *pdwSignerIndex
= 0;
2818 /* Create store to search for signer certificates */
2819 store
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
2820 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
2821 if (!(dwFlags
& CMSG_TRUSTED_SIGNER_FLAG
))
2823 HCERTSTORE msgStore
= CertOpenStore(CERT_STORE_PROV_MSG
, 0, 0, 0,
2826 CertAddStoreToCollection(store
, msgStore
, 0, 0);
2827 CertCloseStore(msgStore
, 0);
2829 for (i
= 0; i
< cSignerStore
; i
++)
2830 CertAddStoreToCollection(store
, rghSignerStore
[i
], 0, 0);
2832 /* Find signer cert */
2833 if (dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
)
2835 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
2840 signerIndex
= *pdwSignerIndex
;
2841 signerCert
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
,
2842 0, CERT_FIND_SUBJECT_CERT
, signer
, NULL
);
2843 CryptMemFree(signer
);
2848 DWORD count
, size
= sizeof(count
);
2850 if (CryptMsgGetParam(hCryptMsg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
,
2853 for (i
= 0; !signerCert
&& i
< count
; i
++)
2855 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
2860 signerCert
= CertFindCertificateInStore(store
,
2861 X509_ASN_ENCODING
, 0, CERT_FIND_SUBJECT_CERT
, signer
,
2865 CryptMemFree(signer
);
2870 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER
);
2874 if (!(dwFlags
& CMSG_SIGNER_ONLY_FLAG
))
2875 ret
= CryptMsgControl(hCryptMsg
, 0, CMSG_CTRL_VERIFY_SIGNATURE
,
2876 signerCert
->pCertInfo
);
2882 *ppSigner
= CertDuplicateCertificateContext(signerCert
);
2884 *pdwSignerIndex
= signerIndex
;
2886 CertFreeCertificateContext(signerCert
);
2889 CertCloseStore(store
, 0);
2893 BOOL WINAPI
CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv
,
2894 DWORD dwEncodingType
, PBYTE pbSignerInfo
, DWORD cbSignerInfo
,
2895 PBYTE pbSignerInfoCountersignature
, DWORD cbSignerInfoCountersignature
,
2896 DWORD dwSignerType
, void *pvSigner
, DWORD dwFlags
, void *pvReserved
)
2898 FIXME("(%08lx, %08x, %p, %d, %p, %d, %d, %p, %08x, %p): stub\n", hCryptProv
,
2899 dwEncodingType
, pbSignerInfo
, cbSignerInfo
, pbSignerInfoCountersignature
,
2900 cbSignerInfoCountersignature
, dwSignerType
, pvSigner
, dwFlags
, pvReserved
);