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
24 #include "wine/debug.h"
25 #include "wine/exception.h"
26 #include "crypt32_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
30 /* Called when a message's ref count reaches zero. Free any message-specific
33 typedef void (*CryptMsgCloseFunc
)(HCRYPTMSG msg
);
35 typedef BOOL (*CryptMsgGetParamFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
36 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
);
38 typedef BOOL (*CryptMsgUpdateFunc
)(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
39 DWORD cbData
, BOOL fFinal
);
41 typedef BOOL (*CryptMsgControlFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
42 DWORD dwCtrlType
, const void *pvCtrlPara
);
44 BOOL
CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
45 DWORD dwCtrlType
, const void *pvCtrlPara
)
47 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
48 SetLastError(E_INVALIDARG
);
52 typedef enum _CryptMsgState
{
58 typedef struct _CryptMsgBase
63 CMSG_STREAM_INFO stream_info
;
65 CryptMsgCloseFunc close
;
66 CryptMsgUpdateFunc update
;
67 CryptMsgGetParamFunc get_param
;
68 CryptMsgControlFunc control
;
71 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
72 PCMSG_STREAM_INFO pStreamInfo
, CryptMsgCloseFunc close
,
73 CryptMsgGetParamFunc get_param
, CryptMsgUpdateFunc update
,
74 CryptMsgControlFunc control
)
77 msg
->open_flags
= dwFlags
;
81 memcpy(&msg
->stream_info
, pStreamInfo
, sizeof(msg
->stream_info
));
85 msg
->streamed
= FALSE
;
86 memset(&msg
->stream_info
, 0, sizeof(msg
->stream_info
));
89 msg
->get_param
= get_param
;
91 msg
->control
= control
;
92 msg
->state
= MsgStateInit
;
95 typedef struct _CDataEncodeMsg
98 DWORD bare_content_len
;
102 static const BYTE empty_data_content
[] = { 0x04,0x00 };
104 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
106 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
108 if (msg
->bare_content
!= empty_data_content
)
109 LocalFree(msg
->bare_content
);
112 static WINAPI BOOL
CRYPT_EncodeContentLength(DWORD dwCertEncodingType
,
113 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
114 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
116 DWORD dataLen
= *(DWORD
*)pvStructInfo
;
120 /* Trick: report bytes needed based on total message length, even though
121 * the message isn't available yet. The caller will use the length
122 * reported here to encode its length.
124 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
126 *pcbEncoded
= 1 + lenBytes
+ dataLen
;
129 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
130 pcbEncoded
, 1 + lenBytes
)))
132 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
133 pbEncoded
= *(BYTE
**)pbEncoded
;
134 *pbEncoded
++ = ASN_OCTETSTRING
;
135 CRYPT_EncodeLen(dataLen
, pbEncoded
,
142 static BOOL
CRYPT_EncodeDataContentInfoHeader(CDataEncodeMsg
*msg
,
143 CRYPT_DATA_BLOB
*header
)
147 if (msg
->base
.streamed
&& msg
->base
.stream_info
.cbContent
== 0xffffffff)
149 static const BYTE headerValue
[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
150 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
152 header
->pbData
= LocalAlloc(0, sizeof(headerValue
));
155 header
->cbData
= sizeof(headerValue
);
156 memcpy(header
->pbData
, headerValue
, sizeof(headerValue
));
164 struct AsnConstructedItem constructed
= { 0,
165 &msg
->base
.stream_info
.cbContent
, CRYPT_EncodeContentLength
};
166 struct AsnEncodeSequenceItem items
[2] = {
167 { szOID_RSA_data
, CRYPT_AsnEncodeOid
, 0 },
168 { &constructed
, CRYPT_AsnEncodeConstructed
, 0 },
171 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
172 sizeof(items
) / sizeof(items
[0]), CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
173 (LPBYTE
)&header
->pbData
, &header
->cbData
);
176 /* Trick: subtract the content length from the reported length,
177 * as the actual content hasn't come yet.
179 header
->cbData
-= msg
->base
.stream_info
.cbContent
;
185 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
186 DWORD cbData
, BOOL fFinal
)
188 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
191 if (msg
->base
.streamed
)
195 if (msg
->base
.state
!= MsgStateUpdated
)
197 CRYPT_DATA_BLOB header
;
199 ret
= CRYPT_EncodeDataContentInfoHeader(msg
, &header
);
202 ret
= msg
->base
.stream_info
.pfnStreamOutput(
203 msg
->base
.stream_info
.pvArg
, header
.pbData
, header
.cbData
,
205 LocalFree(header
.pbData
);
208 /* Curiously, every indefinite-length streamed update appears to
209 * get its own tag and length, regardless of fFinal.
211 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
216 ret
= CRYPT_EncodeContentLength(X509_ASN_ENCODING
, NULL
,
217 &cbData
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (BYTE
*)&header
,
221 ret
= msg
->base
.stream_info
.pfnStreamOutput(
222 msg
->base
.stream_info
.pvArg
, header
, headerLen
,
228 ret
= msg
->base
.stream_info
.pfnStreamOutput(
229 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
233 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
235 BYTE indefinite_trailer
[6] = { 0 };
237 ret
= msg
->base
.stream_info
.pfnStreamOutput(
238 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
241 ret
= msg
->base
.stream_info
.pfnStreamOutput(
242 msg
->base
.stream_info
.pvArg
, indefinite_trailer
,
243 sizeof(indefinite_trailer
), TRUE
);
246 ret
= msg
->base
.stream_info
.pfnStreamOutput(
247 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
, TRUE
);
252 SetLastError(STATUS_ACCESS_VIOLATION
);
261 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
262 SetLastError(E_INVALIDARG
);
264 SetLastError(CRYPT_E_MSG_ERROR
);
269 SetLastError(E_INVALIDARG
);
272 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
274 /* non-streamed data messages don't allow non-final updates,
275 * don't bother checking whether data already exist, they can't.
277 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
278 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
279 &msg
->bare_content_len
);
286 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
293 else if (*pcbData
< len
)
296 SetLastError(ERROR_MORE_DATA
);
302 memcpy(pvData
, src
, len
);
307 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
308 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
310 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
315 case CMSG_CONTENT_PARAM
:
316 if (msg
->base
.streamed
)
317 SetLastError(E_INVALIDARG
);
320 CRYPT_CONTENT_INFO info
;
321 char rsa_data
[] = "1.2.840.113549.1.7.1";
323 info
.pszObjId
= rsa_data
;
324 info
.Content
.cbData
= msg
->bare_content_len
;
325 info
.Content
.pbData
= msg
->bare_content
;
326 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
330 case CMSG_BARE_CONTENT_PARAM
:
331 if (msg
->base
.streamed
)
332 SetLastError(E_INVALIDARG
);
334 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->bare_content
,
335 msg
->bare_content_len
);
338 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
343 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
344 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
350 SetLastError(E_INVALIDARG
);
353 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
356 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
357 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
,
358 CRYPT_DefaultMsgControl
);
359 msg
->bare_content_len
= sizeof(empty_data_content
);
360 msg
->bare_content
= (LPBYTE
)empty_data_content
;
362 return (HCRYPTMSG
)msg
;
365 typedef struct _CHashEncodeMsg
370 CRYPT_DATA_BLOB data
;
373 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
375 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
377 CryptMemFree(msg
->data
.pbData
);
378 CryptDestroyHash(msg
->hash
);
379 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
380 CryptReleaseContext(msg
->prov
, 0);
383 static BOOL
CRYPT_EncodePKCSDigestedData(CHashEncodeMsg
*msg
, void *pvData
,
388 DWORD size
= sizeof(algID
);
390 ret
= CryptGetHashParam(msg
->hash
, HP_ALGID
, (BYTE
*)&algID
, &size
, 0);
393 CRYPT_DIGESTED_DATA digestedData
= { 0 };
394 char oid_rsa_data
[] = szOID_RSA_data
;
396 digestedData
.version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
397 digestedData
.DigestAlgorithm
.pszObjId
= (LPSTR
)CertAlgIdToOID(algID
);
398 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
399 /* Quirk: OID is only encoded messages if an update has happened */
400 if (msg
->base
.state
!= MsgStateInit
)
401 digestedData
.ContentInfo
.pszObjId
= oid_rsa_data
;
402 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->data
.cbData
)
404 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &msg
->data
,
405 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
406 (LPBYTE
)&digestedData
.ContentInfo
.Content
.pbData
,
407 &digestedData
.ContentInfo
.Content
.cbData
);
409 if (msg
->base
.state
== MsgStateFinalized
)
411 size
= sizeof(DWORD
);
412 ret
= CryptGetHashParam(msg
->hash
, HP_HASHSIZE
,
413 (LPBYTE
)&digestedData
.hash
.cbData
, &size
, 0);
416 digestedData
.hash
.pbData
= CryptMemAlloc(
417 digestedData
.hash
.cbData
);
418 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
,
419 digestedData
.hash
.pbData
, &digestedData
.hash
.cbData
, 0);
423 ret
= CRYPT_AsnEncodePKCSDigestedData(&digestedData
, pvData
,
425 CryptMemFree(digestedData
.hash
.pbData
);
426 LocalFree(digestedData
.ContentInfo
.Content
.pbData
);
431 static BOOL
CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
432 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
434 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
437 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
442 case CMSG_BARE_CONTENT_PARAM
:
443 if (msg
->base
.streamed
)
444 SetLastError(E_INVALIDARG
);
446 ret
= CRYPT_EncodePKCSDigestedData(msg
, pvData
, pcbData
);
448 case CMSG_CONTENT_PARAM
:
450 CRYPT_CONTENT_INFO info
;
452 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
453 &info
.Content
.cbData
);
456 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
457 if (info
.Content
.pbData
)
459 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
460 info
.Content
.pbData
, &info
.Content
.cbData
);
463 char oid_rsa_hashed
[] = szOID_RSA_hashedData
;
465 info
.pszObjId
= oid_rsa_hashed
;
466 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
467 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
469 CryptMemFree(info
.Content
.pbData
);
476 case CMSG_COMPUTED_HASH_PARAM
:
477 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
, (BYTE
*)pvData
, pcbData
,
480 case CMSG_VERSION_PARAM
:
481 if (msg
->base
.state
!= MsgStateFinalized
)
482 SetLastError(CRYPT_E_MSG_ERROR
);
485 DWORD version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
487 /* Since the data are always encoded as octets, the version is
488 * always 0 (see rfc3852, section 7)
490 ret
= CRYPT_CopyParam(pvData
, pcbData
, &version
, sizeof(version
));
494 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
499 static BOOL
CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
500 DWORD cbData
, BOOL fFinal
)
502 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
505 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
507 if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
509 /* Doesn't do much, as stream output is never called, and you
510 * can't get the content.
512 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
517 SetLastError(CRYPT_E_MSG_ERROR
);
520 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
523 msg
->data
.pbData
= CryptMemAlloc(cbData
);
524 if (msg
->data
.pbData
)
526 memcpy(msg
->data
.pbData
+ msg
->data
.cbData
, pbData
, cbData
);
527 msg
->data
.cbData
+= cbData
;
537 static HCRYPTMSG
CHashEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
538 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
541 const CMSG_HASHED_ENCODE_INFO
*info
=
542 (const CMSG_HASHED_ENCODE_INFO
*)pvMsgEncodeInfo
;
546 if (info
->cbSize
!= sizeof(CMSG_HASHED_ENCODE_INFO
))
548 SetLastError(E_INVALIDARG
);
551 if (!(algID
= CertOIDToAlgId(info
->HashAlgorithm
.pszObjId
)))
553 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
556 if (info
->hCryptProv
)
557 prov
= info
->hCryptProv
;
560 prov
= CRYPT_GetDefaultProvider();
561 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
563 msg
= CryptMemAlloc(sizeof(CHashEncodeMsg
));
566 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
567 CHashEncodeMsg_Close
, CHashEncodeMsg_GetParam
, CHashEncodeMsg_Update
,
568 CRYPT_DefaultMsgControl
);
570 msg
->data
.cbData
= 0;
571 msg
->data
.pbData
= NULL
;
572 if (!CryptCreateHash(prov
, algID
, 0, 0, &msg
->hash
))
578 return (HCRYPTMSG
)msg
;
581 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
584 PCERT_INFO pCertInfo
;
585 HCRYPTPROV hCryptProv
;
587 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm
;
590 PCRYPT_ATTRIBUTE rgAuthAttr
;
592 PCRYPT_ATTRIBUTE rgUnauthAttr
;
594 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm
;
595 void *pvHashEncryptionAuxInfo
;
596 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS
;
598 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
602 PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners
;
604 PCERT_BLOB rgCertEncoded
;
606 PCRL_BLOB rgCrlEncoded
;
607 DWORD cAttrCertEncoded
;
608 PCERT_BLOB rgAttrCertEncoded
;
609 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS
;
611 static BOOL
CRYPT_IsValidSigner(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*signer
)
613 if (signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO
) &&
614 signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
616 SetLastError(E_INVALIDARG
);
619 if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
621 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
624 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
626 SetLastError(E_INVALIDARG
);
629 if (!signer
->pCertInfo
->Issuer
.cbData
)
631 SetLastError(E_INVALIDARG
);
634 if (!signer
->hCryptProv
)
636 SetLastError(E_INVALIDARG
);
639 if (!CertOIDToAlgId(signer
->HashAlgorithm
.pszObjId
))
641 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
647 static BOOL
CRYPT_ConstructBlob(CRYPT_DATA_BLOB
*out
, const CRYPT_DATA_BLOB
*in
)
651 out
->cbData
= in
->cbData
;
654 out
->pbData
= CryptMemAlloc(out
->cbData
);
656 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
665 typedef struct _BlobArray
668 PCRYPT_DATA_BLOB blobs
;
671 static BOOL
CRYPT_ConstructBlobArray(BlobArray
*out
, const BlobArray
*in
)
675 out
->cBlobs
= in
->cBlobs
;
678 out
->blobs
= CryptMemAlloc(out
->cBlobs
* sizeof(CRYPT_DATA_BLOB
));
683 memset(out
->blobs
, 0, out
->cBlobs
* sizeof(CRYPT_DATA_BLOB
));
684 for (i
= 0; ret
&& i
< out
->cBlobs
; i
++)
685 ret
= CRYPT_ConstructBlob(&out
->blobs
[i
], &in
->blobs
[i
]);
693 static void CRYPT_FreeBlobArray(BlobArray
*array
)
697 for (i
= 0; i
< array
->cBlobs
; i
++)
698 CryptMemFree(array
->blobs
[i
].pbData
);
699 CryptMemFree(array
->blobs
);
702 static BOOL
CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE
*out
,
703 const CRYPT_ATTRIBUTE
*in
)
707 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
710 strcpy(out
->pszObjId
, in
->pszObjId
);
711 ret
= CRYPT_ConstructBlobArray((BlobArray
*)&out
->cValue
,
712 (const BlobArray
*)&in
->cValue
);
719 static BOOL
CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES
*out
,
720 const CRYPT_ATTRIBUTES
*in
)
724 out
->cAttr
= in
->cAttr
;
727 out
->rgAttr
= CryptMemAlloc(out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
732 memset(out
->rgAttr
, 0, out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
733 for (i
= 0; ret
&& i
< out
->cAttr
; i
++)
734 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[i
], &in
->rgAttr
[i
]);
744 /* Constructs a CMSG_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
745 static BOOL
CSignerInfo_Construct(CMSG_SIGNER_INFO
*info
,
746 CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*in
)
750 /* Note: needs to change if CMS fields are supported */
751 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
752 ret
= CRYPT_ConstructBlob(&info
->Issuer
, &in
->pCertInfo
->Issuer
);
754 ret
= CRYPT_ConstructBlob(&info
->SerialNumber
,
755 &in
->pCertInfo
->SerialNumber
);
756 /* Assumption: algorithm IDs will point to static strings, not
757 * stack-based ones, so copying the pointer values is safe.
759 info
->HashAlgorithm
.pszObjId
= in
->HashAlgorithm
.pszObjId
;
761 ret
= CRYPT_ConstructBlob(&info
->HashAlgorithm
.Parameters
,
762 &in
->HashAlgorithm
.Parameters
);
763 memset(&info
->HashEncryptionAlgorithm
, 0,
764 sizeof(info
->HashEncryptionAlgorithm
));
766 ret
= CRYPT_ConstructAttributes(&info
->AuthAttrs
,
767 (CRYPT_ATTRIBUTES
*)&in
->cAuthAttr
);
769 ret
= CRYPT_ConstructAttributes(&info
->UnauthAttrs
,
770 (CRYPT_ATTRIBUTES
*)&in
->cUnauthAttr
);
774 static void CSignerInfo_Free(CMSG_SIGNER_INFO
*info
)
778 CryptMemFree(info
->Issuer
.pbData
);
779 CryptMemFree(info
->SerialNumber
.pbData
);
780 CryptMemFree(info
->HashAlgorithm
.Parameters
.pbData
);
781 CryptMemFree(info
->EncryptedHash
.pbData
);
782 for (i
= 0; i
< info
->AuthAttrs
.cAttr
; i
++)
784 for (j
= 0; j
< info
->AuthAttrs
.rgAttr
[i
].cValue
; j
++)
785 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
786 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
);
787 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].pszObjId
);
789 CryptMemFree(info
->AuthAttrs
.rgAttr
);
790 for (i
= 0; i
< info
->UnauthAttrs
.cAttr
; i
++)
792 for (j
= 0; j
< info
->UnauthAttrs
.rgAttr
[i
].cValue
; j
++)
793 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
794 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
);
795 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].pszObjId
);
797 CryptMemFree(info
->UnauthAttrs
.rgAttr
);
800 typedef struct _CSignerHandles
802 HCRYPTHASH contentHash
;
803 HCRYPTHASH authAttrHash
;
806 typedef struct _CSignedMsgData
808 CRYPT_SIGNED_INFO
*info
;
810 CSignerHandles
*signerHandles
;
813 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
814 * Assumes signerIndex is a valid idnex, and that msg_data's info has already
817 static BOOL
CSignedMsgData_ConstructSignerHandles(CSignedMsgData
*msg_data
,
818 DWORD signerIndex
, HCRYPTPROV crypt_prov
)
823 algID
= CertOIDToAlgId(
824 msg_data
->info
->rgSignerInfo
[signerIndex
].HashAlgorithm
.pszObjId
);
825 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
826 &msg_data
->signerHandles
->contentHash
);
827 if (ret
&& msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
> 0)
828 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
829 &msg_data
->signerHandles
->authAttrHash
);
833 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
836 static BOOL
CSignedMsgData_AllocateHandles(CSignedMsgData
*msg_data
)
840 if (msg_data
->info
->cSignerInfo
)
842 msg_data
->signerHandles
=
843 CryptMemAlloc(msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
844 if (msg_data
->signerHandles
)
846 msg_data
->cSignerHandle
= msg_data
->info
->cSignerInfo
;
847 memset(msg_data
->signerHandles
, 0,
848 msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
852 msg_data
->cSignerHandle
= 0;
858 msg_data
->cSignerHandle
= 0;
859 msg_data
->signerHandles
= NULL
;
864 static void CSignedMsgData_CloseHandles(CSignedMsgData
*msg_data
)
868 for (i
= 0; i
< msg_data
->cSignerHandle
; i
++)
870 if (msg_data
->signerHandles
[i
].contentHash
)
871 CryptDestroyHash(msg_data
->signerHandles
[i
].contentHash
);
872 if (msg_data
->signerHandles
[i
].authAttrHash
)
873 CryptDestroyHash(msg_data
->signerHandles
[i
].authAttrHash
);
875 CryptMemFree(msg_data
->signerHandles
);
876 msg_data
->signerHandles
= NULL
;
877 msg_data
->cSignerHandle
= 0;
880 static BOOL
CSignedMsgData_UpdateHash(CSignedMsgData
*msg_data
,
881 const BYTE
*pbData
, DWORD cbData
)
886 for (i
= 0; ret
&& i
< msg_data
->cSignerHandle
; i
++)
887 ret
= CryptHashData(msg_data
->signerHandles
[i
].contentHash
, pbData
,
892 static BOOL
CRYPT_AppendAttribute(CRYPT_ATTRIBUTES
*out
,
893 const CRYPT_ATTRIBUTE
*in
)
897 out
->rgAttr
= CryptMemRealloc(out
->rgAttr
,
898 (out
->cAttr
+ 1) * sizeof(CRYPT_ATTRIBUTE
));
901 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[out
->cAttr
], in
);
908 static BOOL
CSignedMsgData_AppendMessageDigestAttribute(
909 CSignedMsgData
*msg_data
, DWORD signerIndex
)
913 CRYPT_HASH_BLOB hash
= { 0, NULL
}, encodedHash
= { 0, NULL
};
914 char messageDigest
[] = szOID_RSA_messageDigest
;
915 CRYPT_ATTRIBUTE messageDigestAttr
= { messageDigest
, 1, &encodedHash
};
917 size
= sizeof(DWORD
);
918 ret
= CryptGetHashParam(
919 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHSIZE
,
920 (LPBYTE
)&hash
.cbData
, &size
, 0);
923 hash
.pbData
= CryptMemAlloc(hash
.cbData
);
924 ret
= CryptGetHashParam(
925 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHVAL
,
926 hash
.pbData
, &hash
.cbData
, 0);
929 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &hash
, CRYPT_ENCODE_ALLOC_FLAG
,
930 NULL
, (LPBYTE
)&encodedHash
.pbData
, &encodedHash
.cbData
);
933 ret
= CRYPT_AppendAttribute(
934 &msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
,
936 LocalFree(encodedHash
.pbData
);
939 CryptMemFree(hash
.pbData
);
949 static BOOL
CSignedMsgData_UpdateAuthenticatedAttributes(
950 CSignedMsgData
*msg_data
, SignOrVerify flag
)
955 TRACE("(%p)\n", msg_data
);
957 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
959 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
963 BYTE oid_rsa_data_encoded
[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
964 0xf7,0x0d,0x01,0x07,0x01 };
965 CRYPT_DATA_BLOB content
= { sizeof(oid_rsa_data_encoded
),
966 oid_rsa_data_encoded
};
967 char contentType
[] = szOID_RSA_contentType
;
968 CRYPT_ATTRIBUTE contentTypeAttr
= { contentType
, 1, &content
};
970 /* FIXME: does this depend on inner OID? */
971 ret
= CRYPT_AppendAttribute(
972 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
, &contentTypeAttr
);
974 ret
= CSignedMsgData_AppendMessageDigestAttribute(msg_data
,
982 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, PKCS_ATTRIBUTES
,
983 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
,
984 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&encodedAttrs
, &size
);
988 msg_data
->signerHandles
[i
].authAttrHash
, encodedAttrs
,
990 LocalFree(encodedAttrs
);
995 TRACE("returning %d\n", ret
);
999 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB
*hash
)
1004 for (i
= 0; i
< hash
->cbData
/ 2; i
++)
1006 tmp
= hash
->pbData
[hash
->cbData
- i
- 1];
1007 hash
->pbData
[hash
->cbData
- i
- 1] = hash
->pbData
[i
];
1008 hash
->pbData
[i
] = tmp
;
1012 static BOOL
CSignedMsgData_Sign(CSignedMsgData
*msg_data
)
1017 TRACE("(%p)\n", msg_data
);
1019 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1023 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1024 hash
= msg_data
->signerHandles
[i
].authAttrHash
;
1026 hash
= msg_data
->signerHandles
[i
].contentHash
;
1027 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0, NULL
,
1028 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1031 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
=
1033 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1034 if (msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
)
1036 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0,
1037 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
,
1038 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1041 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
);
1050 static BOOL
CSignedMsgData_Update(CSignedMsgData
*msg_data
,
1051 const BYTE
*pbData
, DWORD cbData
, BOOL fFinal
, SignOrVerify flag
)
1053 BOOL ret
= CSignedMsgData_UpdateHash(msg_data
, pbData
, cbData
);
1057 ret
= CSignedMsgData_UpdateAuthenticatedAttributes(msg_data
, flag
);
1058 if (ret
&& flag
== Sign
)
1059 ret
= CSignedMsgData_Sign(msg_data
);
1064 typedef struct _CSignedEncodeMsg
1067 CRYPT_DATA_BLOB data
;
1068 CSignedMsgData msg_data
;
1071 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1073 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1076 CryptMemFree(msg
->data
.pbData
);
1077 CRYPT_FreeBlobArray((BlobArray
*)&msg
->msg_data
.info
->cCertEncoded
);
1078 CRYPT_FreeBlobArray((BlobArray
*)&msg
->msg_data
.info
->cCrlEncoded
);
1079 for (i
= 0; i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1080 CSignerInfo_Free(&msg
->msg_data
.info
->rgSignerInfo
[i
]);
1081 CSignedMsgData_CloseHandles(&msg
->msg_data
);
1082 CryptMemFree(msg
->msg_data
.info
->rgSignerInfo
);
1083 CryptMemFree(msg
->msg_data
.info
);
1086 static BOOL
CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1087 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1089 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1092 switch (dwParamType
)
1094 case CMSG_CONTENT_PARAM
:
1096 CRYPT_CONTENT_INFO info
;
1098 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1099 &info
.Content
.cbData
);
1102 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1103 if (info
.Content
.pbData
)
1105 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1106 info
.Content
.pbData
, &info
.Content
.cbData
);
1109 char oid_rsa_signed
[] = szOID_RSA_signedData
;
1111 info
.pszObjId
= oid_rsa_signed
;
1112 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1113 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1115 CryptMemFree(info
.Content
.pbData
);
1122 case CMSG_BARE_CONTENT_PARAM
:
1124 CRYPT_SIGNED_INFO info
;
1125 char oid_rsa_data
[] = szOID_RSA_data
;
1127 memcpy(&info
, msg
->msg_data
.info
, sizeof(info
));
1128 /* Quirk: OID is only encoded messages if an update has happened */
1129 if (msg
->base
.state
!= MsgStateInit
)
1130 info
.content
.pszObjId
= oid_rsa_data
;
1132 info
.content
.pszObjId
= NULL
;
1133 if (msg
->data
.cbData
)
1135 CRYPT_DATA_BLOB blob
= { msg
->data
.cbData
, msg
->data
.pbData
};
1137 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1138 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
1139 &info
.content
.Content
.pbData
, &info
.content
.Content
.cbData
);
1143 info
.content
.Content
.cbData
= 0;
1144 info
.content
.Content
.pbData
= NULL
;
1149 ret
= CRYPT_AsnEncodePKCSSignedInfo(&info
, pvData
, pcbData
);
1150 LocalFree(info
.content
.Content
.pbData
);
1154 case CMSG_COMPUTED_HASH_PARAM
:
1155 if (dwIndex
>= msg
->msg_data
.cSignerHandle
)
1156 SetLastError(CRYPT_E_INVALID_INDEX
);
1158 ret
= CryptGetHashParam(
1159 msg
->msg_data
.signerHandles
[dwIndex
].contentHash
, HP_HASHVAL
,
1160 pvData
, pcbData
, 0);
1162 case CMSG_ENCODED_SIGNER
:
1163 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1164 SetLastError(CRYPT_E_INVALID_INDEX
);
1166 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1167 PKCS7_SIGNER_INFO
, &msg
->msg_data
.info
->rgSignerInfo
[dwIndex
], 0,
1168 NULL
, pvData
, pcbData
);
1170 case CMSG_VERSION_PARAM
:
1171 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->msg_data
.info
->version
,
1172 sizeof(msg
->msg_data
.info
->version
));
1175 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1180 static BOOL
CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1181 DWORD cbData
, BOOL fFinal
)
1183 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1186 if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1188 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
, fFinal
,
1190 if (msg
->base
.streamed
)
1191 FIXME("streamed partial stub\n");
1196 SetLastError(CRYPT_E_MSG_ERROR
);
1201 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1202 if (msg
->data
.pbData
)
1204 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1205 msg
->data
.cbData
= cbData
;
1212 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
,
1219 static HCRYPTMSG
CSignedEncodeMsg_Open(DWORD dwFlags
,
1220 const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
1221 PCMSG_STREAM_INFO pStreamInfo
)
1223 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*info
=
1224 (const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*)pvMsgEncodeInfo
;
1226 CSignedEncodeMsg
*msg
;
1228 if (info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO
) &&
1229 info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1231 SetLastError(E_INVALIDARG
);
1234 if (info
->cbSize
== sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1236 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1239 for (i
= 0; i
< info
->cSigners
; i
++)
1240 if (!CRYPT_IsValidSigner(&info
->rgSigners
[i
]))
1242 msg
= CryptMemAlloc(sizeof(CSignedEncodeMsg
));
1247 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1248 CSignedEncodeMsg_Close
, CSignedEncodeMsg_GetParam
,
1249 CSignedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1250 msg
->data
.cbData
= 0;
1251 msg
->data
.pbData
= NULL
;
1252 msg
->msg_data
.info
= CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO
));
1253 if (msg
->msg_data
.info
)
1255 memset(msg
->msg_data
.info
, 0, sizeof(CRYPT_SIGNED_INFO
));
1256 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V1
;
1264 msg
->msg_data
.info
->rgSignerInfo
=
1265 CryptMemAlloc(info
->cSigners
* sizeof(CMSG_SIGNER_INFO
));
1266 if (msg
->msg_data
.info
->rgSignerInfo
)
1268 msg
->msg_data
.info
->cSignerInfo
= info
->cSigners
;
1269 memset(msg
->msg_data
.info
->rgSignerInfo
, 0,
1270 msg
->msg_data
.info
->cSignerInfo
* sizeof(CMSG_SIGNER_INFO
));
1271 ret
= CSignedMsgData_AllocateHandles(&msg
->msg_data
);
1272 for (i
= 0; ret
&& i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1274 ret
= CSignerInfo_Construct(
1275 &msg
->msg_data
.info
->rgSignerInfo
[i
],
1276 &info
->rgSigners
[i
]);
1279 ret
= CSignedMsgData_ConstructSignerHandles(
1280 &msg
->msg_data
, i
, info
->rgSigners
[i
].hCryptProv
);
1281 if (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1282 CryptReleaseContext(info
->rgSigners
[i
].hCryptProv
,
1292 msg
->msg_data
.info
->cSignerInfo
= 0;
1293 msg
->msg_data
.signerHandles
= NULL
;
1294 msg
->msg_data
.cSignerHandle
= 0;
1298 ret
= CRYPT_ConstructBlobArray(
1299 (BlobArray
*)&msg
->msg_data
.info
->cCertEncoded
,
1300 (const BlobArray
*)&info
->cCertEncoded
);
1302 ret
= CRYPT_ConstructBlobArray(
1303 (BlobArray
*)&msg
->msg_data
.info
->cCrlEncoded
,
1304 (const BlobArray
*)&info
->cCrlEncoded
);
1307 CSignedEncodeMsg_Close(msg
);
1314 static inline const char *MSG_TYPE_STR(DWORD type
)
1318 #define _x(x) case (x): return #x
1322 _x(CMSG_SIGNED_AND_ENVELOPED
);
1327 return wine_dbg_sprintf("unknown (%d)", type
);
1331 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
1332 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
1333 PCMSG_STREAM_INFO pStreamInfo
)
1335 HCRYPTMSG msg
= NULL
;
1337 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
1338 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
1340 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
1342 SetLastError(E_INVALIDARG
);
1348 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1349 pszInnerContentObjID
, pStreamInfo
);
1352 msg
= CHashEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1353 pszInnerContentObjID
, pStreamInfo
);
1356 msg
= CSignedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1357 pszInnerContentObjID
, pStreamInfo
);
1359 case CMSG_ENVELOPED
:
1360 FIXME("unimplemented for type %s\n", MSG_TYPE_STR(dwMsgType
));
1362 case CMSG_SIGNED_AND_ENVELOPED
:
1363 case CMSG_ENCRYPTED
:
1364 /* defined but invalid, fall through */
1366 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1371 typedef struct _CDecodeMsg
1375 HCRYPTPROV crypt_prov
;
1378 CSignedMsgData signed_data
;
1380 CRYPT_DATA_BLOB msg_data
;
1381 PCONTEXT_PROPERTY_LIST properties
;
1384 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg
)
1386 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
1388 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1389 CryptReleaseContext(msg
->crypt_prov
, 0);
1394 CryptDestroyHash(msg
->u
.hash
);
1397 if (msg
->u
.signed_data
.info
)
1399 LocalFree(msg
->u
.signed_data
.info
);
1400 CSignedMsgData_CloseHandles(&msg
->u
.signed_data
);
1404 CryptMemFree(msg
->msg_data
.pbData
);
1405 ContextPropertyList_Free(msg
->properties
);
1408 static BOOL
CDecodeMsg_CopyData(CDecodeMsg
*msg
, const BYTE
*pbData
,
1415 if (msg
->msg_data
.cbData
)
1416 msg
->msg_data
.pbData
= CryptMemRealloc(msg
->msg_data
.pbData
,
1417 msg
->msg_data
.cbData
+ cbData
);
1419 msg
->msg_data
.pbData
= CryptMemAlloc(cbData
);
1420 if (msg
->msg_data
.pbData
)
1422 memcpy(msg
->msg_data
.pbData
+ msg
->msg_data
.cbData
, pbData
, cbData
);
1423 msg
->msg_data
.cbData
+= cbData
;
1431 static BOOL
CDecodeMsg_DecodeDataContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
1434 CRYPT_DATA_BLOB
*data
;
1437 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1438 blob
->pbData
, blob
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&data
,
1442 ret
= ContextPropertyList_SetProperty(msg
->properties
,
1443 CMSG_CONTENT_PARAM
, data
->pbData
, data
->cbData
);
1449 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg
*msg
, DWORD param
,
1450 const CRYPT_ALGORITHM_IDENTIFIER
*id
)
1452 static const BYTE nullParams
[] = { ASN_NULL
, 0 };
1453 CRYPT_ALGORITHM_IDENTIFIER
*copy
;
1454 DWORD len
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
1456 /* Linearize algorithm id */
1457 len
+= strlen(id
->pszObjId
) + 1;
1458 len
+= id
->Parameters
.cbData
;
1459 copy
= CryptMemAlloc(len
);
1463 (LPSTR
)((BYTE
*)copy
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
1464 strcpy(copy
->pszObjId
, id
->pszObjId
);
1465 copy
->Parameters
.pbData
= (BYTE
*)copy
->pszObjId
+ strlen(id
->pszObjId
)
1467 /* Trick: omit NULL parameters */
1468 if (id
->Parameters
.cbData
== sizeof(nullParams
) &&
1469 !memcmp(id
->Parameters
.pbData
, nullParams
, sizeof(nullParams
)))
1471 copy
->Parameters
.cbData
= 0;
1472 len
-= sizeof(nullParams
);
1475 copy
->Parameters
.cbData
= id
->Parameters
.cbData
;
1476 if (copy
->Parameters
.cbData
)
1477 memcpy(copy
->Parameters
.pbData
, id
->Parameters
.pbData
,
1478 id
->Parameters
.cbData
);
1479 ContextPropertyList_SetProperty(msg
->properties
, param
, (BYTE
*)copy
,
1485 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER
*id
)
1487 id
->pszObjId
= (LPSTR
)((BYTE
*)id
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
1488 id
->Parameters
.pbData
= (BYTE
*)id
->pszObjId
+ strlen(id
->pszObjId
) + 1;
1491 static BOOL
CDecodeMsg_DecodeHashedContent(CDecodeMsg
*msg
,
1492 CRYPT_DER_BLOB
*blob
)
1495 CRYPT_DIGESTED_DATA
*digestedData
;
1498 ret
= CRYPT_AsnDecodePKCSDigestedData(blob
->pbData
, blob
->cbData
,
1499 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_DIGESTED_DATA
*)&digestedData
,
1503 ContextPropertyList_SetProperty(msg
->properties
, CMSG_VERSION_PARAM
,
1504 (const BYTE
*)&digestedData
->version
, sizeof(digestedData
->version
));
1505 CDecodeMsg_SaveAlgorithmID(msg
, CMSG_HASH_ALGORITHM_PARAM
,
1506 &digestedData
->DigestAlgorithm
);
1507 ContextPropertyList_SetProperty(msg
->properties
,
1508 CMSG_INNER_CONTENT_TYPE_PARAM
,
1509 (const BYTE
*)digestedData
->ContentInfo
.pszObjId
,
1510 digestedData
->ContentInfo
.pszObjId
?
1511 strlen(digestedData
->ContentInfo
.pszObjId
) + 1 : 0);
1512 if (digestedData
->ContentInfo
.Content
.cbData
)
1513 CDecodeMsg_DecodeDataContent(msg
,
1514 &digestedData
->ContentInfo
.Content
);
1516 ContextPropertyList_SetProperty(msg
->properties
,
1517 CMSG_CONTENT_PARAM
, NULL
, 0);
1518 ContextPropertyList_SetProperty(msg
->properties
, CMSG_HASH_DATA_PARAM
,
1519 digestedData
->hash
.pbData
, digestedData
->hash
.cbData
);
1520 LocalFree(digestedData
);
1525 static BOOL
CDecodeMsg_DecodeSignedContent(CDecodeMsg
*msg
,
1526 CRYPT_DER_BLOB
*blob
)
1529 CRYPT_SIGNED_INFO
*signedInfo
;
1532 ret
= CRYPT_AsnDecodePKCSSignedInfo(blob
->pbData
, blob
->cbData
,
1533 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_SIGNED_INFO
*)&signedInfo
,
1539 msg
->u
.signed_data
.info
= signedInfo
;
1540 ret
= CSignedMsgData_AllocateHandles(&msg
->u
.signed_data
);
1541 for (i
= 0; ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
1542 ret
= CSignedMsgData_ConstructSignerHandles(&msg
->u
.signed_data
, i
,
1546 /* Now that we have all the content, update the hash handles with
1547 * it. Have to decode it if the type is szOID_RSA_data.
1549 if (msg
->u
.signed_data
.info
->content
.Content
.cbData
)
1551 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
1554 CRYPT_DATA_BLOB
*blob
;
1556 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
,
1558 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
1559 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
1560 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&blob
, &size
);
1563 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
1564 blob
->pbData
, blob
->cbData
, TRUE
, Verify
);
1569 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
1570 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
1571 msg
->u
.signed_data
.info
->content
.Content
.cbData
, TRUE
,
1578 /* Decodes the content in blob as the type given, and updates the value
1579 * (type, parameters, etc.) of msg based on what blob contains.
1580 * It doesn't just use msg's type, to allow a recursive call from an implicitly
1581 * typed message once the outer content info has been decoded.
1583 static BOOL
CDecodeMsg_DecodeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
,
1591 if ((ret
= CDecodeMsg_DecodeDataContent(msg
, blob
)))
1592 msg
->type
= CMSG_DATA
;
1595 if ((ret
= CDecodeMsg_DecodeHashedContent(msg
, blob
)))
1596 msg
->type
= CMSG_HASHED
;
1598 case CMSG_ENVELOPED
:
1599 FIXME("unimplemented for type %s\n", MSG_TYPE_STR(type
));
1603 if ((ret
= CDecodeMsg_DecodeSignedContent(msg
, blob
)))
1604 msg
->type
= CMSG_SIGNED
;
1608 CRYPT_CONTENT_INFO
*info
;
1611 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
,
1612 msg
->msg_data
.pbData
, msg
->msg_data
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
1613 NULL
, (LPBYTE
)&info
, &size
);
1616 if (!strcmp(info
->pszObjId
, szOID_RSA_data
))
1617 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
, CMSG_DATA
);
1618 else if (!strcmp(info
->pszObjId
, szOID_RSA_digestedData
))
1619 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1621 else if (!strcmp(info
->pszObjId
, szOID_RSA_envelopedData
))
1622 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1624 else if (!strcmp(info
->pszObjId
, szOID_RSA_signedData
))
1625 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1629 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1639 static BOOL
CDecodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1640 DWORD cbData
, BOOL fFinal
)
1642 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
1645 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
1647 if (msg
->base
.streamed
)
1649 ret
= CDecodeMsg_CopyData(msg
, pbData
, cbData
);
1650 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg
, pbData
,
1656 SetLastError(CRYPT_E_MSG_ERROR
);
1659 ret
= CDecodeMsg_CopyData(msg
, pbData
, cbData
);
1661 ret
= CDecodeMsg_DecodeContent(msg
, &msg
->msg_data
, msg
->type
);
1668 static BOOL
CDecodeHashMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
1669 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1673 switch (dwParamType
)
1675 case CMSG_TYPE_PARAM
:
1676 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
1678 case CMSG_HASH_ALGORITHM_PARAM
:
1680 CRYPT_DATA_BLOB blob
;
1682 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
1686 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
1688 CRYPT_FixUpAlgorithmID((CRYPT_ALGORITHM_IDENTIFIER
*)pvData
);
1691 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1694 case CMSG_COMPUTED_HASH_PARAM
:
1697 CRYPT_ALGORITHM_IDENTIFIER
*hashAlgoID
= NULL
;
1701 CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, NULL
, &size
);
1702 hashAlgoID
= CryptMemAlloc(size
);
1703 ret
= CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0,
1706 algID
= CertOIDToAlgId(hashAlgoID
->pszObjId
);
1707 ret
= CryptCreateHash(msg
->crypt_prov
, algID
, 0, 0, &msg
->u
.hash
);
1710 CRYPT_DATA_BLOB content
;
1712 ret
= ContextPropertyList_FindProperty(msg
->properties
,
1713 CMSG_CONTENT_PARAM
, &content
);
1715 ret
= CryptHashData(msg
->u
.hash
, content
.pbData
,
1718 CryptMemFree(hashAlgoID
);
1723 ret
= CryptGetHashParam(msg
->u
.hash
, HP_HASHVAL
, pvData
, pcbData
,
1728 CRYPT_DATA_BLOB blob
;
1730 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
1733 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
1735 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1741 /* nextData is an in/out parameter - on input it's the memory location in
1742 * which a copy of in's data should be made, and on output it's the memory
1743 * location immediately after out's copy of in's data.
1745 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB
*out
,
1746 const CRYPT_DATA_BLOB
*in
, LPBYTE
*nextData
)
1748 out
->cbData
= in
->cbData
;
1751 out
->pbData
= *nextData
;
1752 memcpy(out
->pbData
, in
->pbData
, in
->cbData
);
1753 *nextData
+= in
->cbData
;
1757 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
1758 const CRYPT_ALGORITHM_IDENTIFIER
*in
, LPBYTE
*nextData
)
1762 out
->pszObjId
= (LPSTR
)*nextData
;
1763 strcpy(out
->pszObjId
, in
->pszObjId
);
1764 *nextData
+= strlen(out
->pszObjId
) + 1;
1766 CRYPT_CopyBlob(&out
->Parameters
, &in
->Parameters
, nextData
);
1769 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES
*out
,
1770 const CRYPT_ATTRIBUTES
*in
, LPBYTE
*nextData
)
1772 out
->cAttr
= in
->cAttr
;
1777 if ((*nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
))
1778 *nextData
+= (*nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
);
1779 out
->rgAttr
= (CRYPT_ATTRIBUTE
*)*nextData
;
1780 *nextData
+= in
->cAttr
* sizeof(CRYPT_ATTRIBUTE
);
1781 for (i
= 0; i
< in
->cAttr
; i
++)
1783 if (in
->rgAttr
[i
].pszObjId
)
1785 out
->rgAttr
[i
].pszObjId
= (LPSTR
)*nextData
;
1786 strcpy(out
->rgAttr
[i
].pszObjId
, in
->rgAttr
[i
].pszObjId
);
1787 *nextData
+= strlen(in
->rgAttr
[i
].pszObjId
) + 1;
1789 if (in
->rgAttr
[i
].cValue
)
1793 out
->rgAttr
[i
].cValue
= in
->rgAttr
[i
].cValue
;
1794 if ((*nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
))
1795 *nextData
+= (*nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
);
1796 out
->rgAttr
[i
].rgValue
= (PCRYPT_DATA_BLOB
)*nextData
;
1797 *nextData
+= in
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
1798 for (j
= 0; j
< in
->rgAttr
[i
].cValue
; j
++)
1799 CRYPT_CopyBlob(&out
->rgAttr
[i
].rgValue
[j
],
1800 &in
->rgAttr
[i
].rgValue
[j
], nextData
);
1806 static DWORD
CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES
*attr
)
1808 DWORD size
= attr
->cAttr
* sizeof(CRYPT_ATTRIBUTE
), i
, j
;
1810 for (i
= 0; i
< attr
->cAttr
; i
++)
1812 if (attr
->rgAttr
[i
].pszObjId
)
1813 size
+= strlen(attr
->rgAttr
[i
].pszObjId
) + 1;
1815 if (size
% sizeof(DWORD_PTR
))
1816 size
+= size
% sizeof(DWORD_PTR
);
1817 size
+= attr
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
1818 for (j
= 0; j
< attr
->rgAttr
[i
].cValue
; j
++)
1819 size
+= attr
->rgAttr
[i
].rgValue
[j
].cbData
;
1821 /* align pointer again to be conservative */
1822 if (size
% sizeof(DWORD_PTR
))
1823 size
+= size
% sizeof(DWORD_PTR
);
1827 static BOOL
CRYPT_CopySignerInfo(void *pvData
, DWORD
*pcbData
,
1828 const CMSG_SIGNER_INFO
*in
)
1830 DWORD size
= sizeof(CMSG_SIGNER_INFO
);
1833 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
1835 size
+= in
->Issuer
.cbData
;
1836 size
+= in
->SerialNumber
.cbData
;
1837 if (in
->HashAlgorithm
.pszObjId
)
1838 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
1839 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
1840 if (in
->HashEncryptionAlgorithm
.pszObjId
)
1841 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
1842 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
1843 size
+= in
->EncryptedHash
.cbData
;
1845 if (size
% sizeof(DWORD_PTR
))
1846 size
+= size
% sizeof(DWORD_PTR
);
1847 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
1848 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
1854 else if (*pcbData
< size
)
1857 SetLastError(ERROR_MORE_DATA
);
1862 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_SIGNER_INFO
);
1863 CMSG_SIGNER_INFO
*out
= (CMSG_SIGNER_INFO
*)pvData
;
1865 out
->dwVersion
= in
->dwVersion
;
1866 CRYPT_CopyBlob(&out
->Issuer
, &in
->Issuer
, &nextData
);
1867 CRYPT_CopyBlob(&out
->SerialNumber
, &in
->SerialNumber
, &nextData
);
1868 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
1870 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
1871 &in
->HashEncryptionAlgorithm
, &nextData
);
1872 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
1874 if ((nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
))
1875 nextData
+= (nextData
- (LPBYTE
)0) % sizeof(DWORD_PTR
);
1876 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
1877 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
1880 TRACE("returning %d\n", ret
);
1884 static BOOL
CRYPT_CopySignerCertInfo(void *pvData
, DWORD
*pcbData
,
1885 const CMSG_SIGNER_INFO
*in
)
1887 DWORD size
= sizeof(CERT_INFO
);
1890 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
1892 size
+= in
->Issuer
.cbData
;
1893 size
+= in
->SerialNumber
.cbData
;
1899 else if (*pcbData
< size
)
1902 SetLastError(ERROR_MORE_DATA
);
1907 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
1908 CERT_INFO
*out
= (CERT_INFO
*)pvData
;
1910 memset(out
, 0, sizeof(CERT_INFO
));
1911 CRYPT_CopyBlob(&out
->Issuer
, &in
->Issuer
, &nextData
);
1912 CRYPT_CopyBlob(&out
->SerialNumber
, &in
->SerialNumber
, &nextData
);
1915 TRACE("returning %d\n", ret
);
1919 static BOOL
CDecodeSignedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
1920 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1924 switch (dwParamType
)
1926 case CMSG_TYPE_PARAM
:
1927 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
1929 case CMSG_CONTENT_PARAM
:
1930 if (msg
->u
.signed_data
.info
)
1932 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
1935 CRYPT_DATA_BLOB
*blob
;
1938 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1939 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
1940 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
1941 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&blob
, &size
);
1944 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
->pbData
,
1950 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1951 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
1952 msg
->u
.signed_data
.info
->content
.Content
.cbData
);
1955 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1957 case CMSG_INNER_CONTENT_TYPE_PARAM
:
1958 if (msg
->u
.signed_data
.info
)
1959 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1960 msg
->u
.signed_data
.info
->content
.pszObjId
,
1961 strlen(msg
->u
.signed_data
.info
->content
.pszObjId
) + 1);
1963 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1965 case CMSG_SIGNER_COUNT_PARAM
:
1966 if (msg
->u
.signed_data
.info
)
1967 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1968 &msg
->u
.signed_data
.info
->cSignerInfo
, sizeof(DWORD
));
1970 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1972 case CMSG_SIGNER_INFO_PARAM
:
1973 if (msg
->u
.signed_data
.info
)
1975 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
1976 SetLastError(CRYPT_E_INVALID_INDEX
);
1978 ret
= CRYPT_CopySignerInfo(pvData
, pcbData
,
1979 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
1982 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1984 case CMSG_SIGNER_CERT_INFO_PARAM
:
1985 if (msg
->u
.signed_data
.info
)
1987 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
1988 SetLastError(CRYPT_E_INVALID_INDEX
);
1990 ret
= CRYPT_CopySignerCertInfo(pvData
, pcbData
,
1991 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
1994 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1996 case CMSG_CERT_COUNT_PARAM
:
1997 if (msg
->u
.signed_data
.info
)
1998 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1999 &msg
->u
.signed_data
.info
->cCertEncoded
, sizeof(DWORD
));
2001 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2003 case CMSG_CERT_PARAM
:
2004 if (msg
->u
.signed_data
.info
)
2006 if (dwIndex
>= msg
->u
.signed_data
.info
->cCertEncoded
)
2007 SetLastError(CRYPT_E_INVALID_INDEX
);
2009 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2010 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].pbData
,
2011 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].cbData
);
2014 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2016 case CMSG_CRL_COUNT_PARAM
:
2017 if (msg
->u
.signed_data
.info
)
2018 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2019 &msg
->u
.signed_data
.info
->cCrlEncoded
, sizeof(DWORD
));
2021 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2023 case CMSG_CRL_PARAM
:
2024 if (msg
->u
.signed_data
.info
)
2026 if (dwIndex
>= msg
->u
.signed_data
.info
->cCrlEncoded
)
2027 SetLastError(CRYPT_E_INVALID_INDEX
);
2029 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2030 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].pbData
,
2031 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].cbData
);
2034 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2036 case CMSG_COMPUTED_HASH_PARAM
:
2037 if (msg
->u
.signed_data
.info
)
2039 if (dwIndex
>= msg
->u
.signed_data
.cSignerHandle
)
2040 SetLastError(CRYPT_E_INVALID_INDEX
);
2042 ret
= CryptGetHashParam(
2043 msg
->u
.signed_data
.signerHandles
[dwIndex
].contentHash
,
2044 HP_HASHVAL
, pvData
, pcbData
, 0);
2047 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2049 case CMSG_ATTR_CERT_COUNT_PARAM
:
2050 if (msg
->u
.signed_data
.info
)
2052 DWORD attrCertCount
= 0;
2054 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2055 &attrCertCount
, sizeof(DWORD
));
2058 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2060 case CMSG_ATTR_CERT_PARAM
:
2061 if (msg
->u
.signed_data
.info
)
2062 SetLastError(CRYPT_E_INVALID_INDEX
);
2064 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2067 FIXME("unimplemented for %d\n", dwParamType
);
2068 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2073 static BOOL
CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
2074 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2076 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
2082 ret
= CDecodeHashMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2086 ret
= CDecodeSignedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2090 switch (dwParamType
)
2092 case CMSG_TYPE_PARAM
:
2093 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
,
2098 CRYPT_DATA_BLOB blob
;
2100 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2103 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
,
2106 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2113 static BOOL
CDecodeHashMsg_VerifyHash(CDecodeMsg
*msg
)
2116 CRYPT_DATA_BLOB hashBlob
;
2118 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2119 CMSG_HASH_DATA_PARAM
, &hashBlob
);
2122 DWORD computedHashSize
= 0;
2124 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
,
2126 if (hashBlob
.cbData
== computedHashSize
)
2128 LPBYTE computedHash
= CryptMemAlloc(computedHashSize
);
2132 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
2133 computedHash
, &computedHashSize
);
2135 ret
= !memcmp(hashBlob
.pbData
, computedHash
,
2137 CryptMemFree(computedHash
);
2146 static BOOL
CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg
*msg
,
2147 HCRYPTPROV prov
, DWORD signerIndex
, PCERT_PUBLIC_KEY_INFO keyInfo
)
2153 prov
= msg
->crypt_prov
;
2154 ret
= CryptImportPublicKeyInfo(prov
, X509_ASN_ENCODING
, keyInfo
, &key
);
2158 CRYPT_HASH_BLOB reversedHash
;
2160 if (msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
)
2161 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].authAttrHash
;
2163 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].contentHash
;
2164 ret
= CRYPT_ConstructBlob(&reversedHash
,
2165 &msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].EncryptedHash
);
2168 CRYPT_ReverseBytes(&reversedHash
);
2169 ret
= CryptVerifySignatureW(hash
, reversedHash
.pbData
,
2170 reversedHash
.cbData
, key
, NULL
, 0);
2171 CryptMemFree(reversedHash
.pbData
);
2173 CryptDestroyKey(key
);
2178 static BOOL
CDecodeSignedMsg_VerifySignature(CDecodeMsg
*msg
, PCERT_INFO info
)
2183 for (i
= 0; !ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
2185 ret
= CertCompareCertificateName(X509_ASN_ENCODING
,
2186 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
].Issuer
, &info
->Issuer
);
2189 ret
= CertCompareIntegerBlob(
2190 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
].SerialNumber
,
2191 &info
->SerialNumber
);
2197 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, 0, i
,
2198 &info
->SubjectPublicKeyInfo
);
2200 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2205 static BOOL
CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg
*msg
,
2206 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para
)
2210 if (para
->cbSize
!= sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
))
2211 SetLastError(ERROR_INVALID_PARAMETER
);
2212 else if (para
->dwSignerIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2213 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2216 switch (para
->dwSignerType
)
2218 case CMSG_VERIFY_SIGNER_PUBKEY
:
2219 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
,
2220 para
->hCryptProv
, para
->dwSignerIndex
,
2221 (PCERT_PUBLIC_KEY_INFO
)para
->pvSigner
);
2223 case CMSG_VERIFY_SIGNER_CERT
:
2225 PCCERT_CONTEXT cert
= (PCCERT_CONTEXT
)para
->pvSigner
;
2227 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, para
->hCryptProv
,
2228 para
->dwSignerIndex
, &cert
->pCertInfo
->SubjectPublicKeyInfo
);
2232 FIXME("unimplemented for signer type %d\n", para
->dwSignerType
);
2233 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2239 static BOOL
CDecodeMsg_Control(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
2240 DWORD dwCtrlType
, const void *pvCtrlPara
)
2242 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
2247 case CMSG_CTRL_VERIFY_SIGNATURE
:
2251 ret
= CDecodeSignedMsg_VerifySignature(msg
, (PCERT_INFO
)pvCtrlPara
);
2254 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2257 case CMSG_CTRL_DECRYPT
:
2261 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2264 case CMSG_CTRL_VERIFY_HASH
:
2268 ret
= CDecodeHashMsg_VerifyHash(msg
);
2271 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2274 case CMSG_CTRL_VERIFY_SIGNATURE_EX
:
2278 ret
= CDecodeSignedMsg_VerifySignatureEx(msg
,
2279 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
)pvCtrlPara
);
2282 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2286 SetLastError(CRYPT_E_CONTROL_TYPE
);
2291 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
2292 DWORD dwMsgType
, HCRYPTPROV_LEGACY hCryptProv
, PCERT_INFO pRecipientInfo
,
2293 PCMSG_STREAM_INFO pStreamInfo
)
2297 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType
,
2298 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
2300 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
2302 SetLastError(E_INVALIDARG
);
2305 msg
= CryptMemAlloc(sizeof(CDecodeMsg
));
2308 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
2309 CDecodeMsg_Close
, CDecodeMsg_GetParam
, CDecodeMsg_Update
,
2310 CDecodeMsg_Control
);
2311 msg
->type
= dwMsgType
;
2313 msg
->crypt_prov
= hCryptProv
;
2316 msg
->crypt_prov
= CRYPT_GetDefaultProvider();
2317 msg
->base
.open_flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
2319 memset(&msg
->u
, 0, sizeof(msg
->u
));
2320 msg
->msg_data
.cbData
= 0;
2321 msg
->msg_data
.pbData
= NULL
;
2322 msg
->properties
= ContextPropertyList_Create();
2327 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
2329 TRACE("(%p)\n", hCryptMsg
);
2333 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2335 InterlockedIncrement(&msg
->ref
);
2340 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
2342 TRACE("(%p)\n", hCryptMsg
);
2346 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2348 if (InterlockedDecrement(&msg
->ref
) == 0)
2350 TRACE("freeing %p\n", msg
);
2359 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
2360 DWORD cbData
, BOOL fFinal
)
2362 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2365 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
2367 if (msg
->state
== MsgStateFinalized
)
2368 SetLastError(CRYPT_E_MSG_ERROR
);
2371 ret
= msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
2372 msg
->state
= MsgStateUpdated
;
2374 msg
->state
= MsgStateFinalized
;
2379 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
2380 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2382 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2384 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
2386 return msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);
2389 BOOL WINAPI
CryptMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
2390 DWORD dwCtrlType
, const void *pvCtrlPara
)
2392 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2394 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
,
2396 return msg
->control(hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
2399 HCERTSTORE WINAPI
CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType
,
2400 HCRYPTPROV_LEGACY hCryptProv
, DWORD dwFlags
, const BYTE
* pbSignedBlob
,
2403 CRYPT_DATA_BLOB blob
= { cbSignedBlob
, (LPBYTE
)pbSignedBlob
};
2405 TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType
, hCryptProv
,
2406 dwFlags
, pbSignedBlob
, cbSignedBlob
);
2408 return CertOpenStore(CERT_STORE_PROV_PKCS7
, dwMsgAndCertEncodingType
,
2409 hCryptProv
, dwFlags
, &blob
);
2412 LONG WINAPI
CryptGetMessageSignerCount(DWORD dwMsgEncodingType
,
2413 const BYTE
*pbSignedBlob
, DWORD cbSignedBlob
)
2418 TRACE("(%08x, %p, %d)\n", dwMsgEncodingType
, pbSignedBlob
, cbSignedBlob
);
2420 msg
= CryptMsgOpenToDecode(dwMsgEncodingType
, 0, 0, 0, NULL
, NULL
);
2423 if (CryptMsgUpdate(msg
, pbSignedBlob
, cbSignedBlob
, TRUE
))
2425 DWORD size
= sizeof(count
);
2427 CryptMsgGetParam(msg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
, &size
);
2434 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
2435 DWORD dwSignerIndex
)
2437 CERT_INFO
*certInfo
= NULL
;
2440 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
2443 certInfo
= CryptMemAlloc(size
);
2446 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
2447 dwSignerIndex
, certInfo
, &size
))
2449 CryptMemFree(certInfo
);
2457 static PCCERT_CONTEXT WINAPI
CRYPT_DefaultGetSignerCertificate(void *pvGetArg
,
2458 DWORD dwCertEncodingType
, PCERT_INFO pSignerId
, HCERTSTORE hMsgCertStore
)
2460 return CertFindCertificateInStore(hMsgCertStore
, dwCertEncodingType
, 0,
2461 CERT_FIND_SUBJECT_CERT
, pSignerId
, NULL
);
2464 static inline PCCERT_CONTEXT
CRYPT_GetSignerCertificate(HCRYPTMSG msg
,
2465 PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara
, PCERT_INFO certInfo
, HCERTSTORE store
)
2467 PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert
;
2469 if (pVerifyPara
->pfnGetSignerCertificate
)
2470 getCert
= pVerifyPara
->pfnGetSignerCertificate
;
2472 getCert
= CRYPT_DefaultGetSignerCertificate
;
2473 return getCert(pVerifyPara
->pvGetArg
,
2474 pVerifyPara
->dwMsgAndCertEncodingType
, certInfo
, store
);
2477 BOOL WINAPI
CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara
,
2478 DWORD dwSignerIndex
, const BYTE
* pbSignedBlob
, DWORD cbSignedBlob
,
2479 BYTE
* pbDecoded
, DWORD
* pcbDecoded
, PCCERT_CONTEXT
* ppSignerCert
)
2483 CRYPT_CONTENT_INFO
*contentInfo
;
2485 TRACE("(%p, %d, %p, %d, %p, %p, %p)\n",
2486 pVerifyPara
, dwSignerIndex
, pbSignedBlob
, cbSignedBlob
,
2487 pbDecoded
, pcbDecoded
, ppSignerCert
);
2490 *ppSignerCert
= NULL
;
2494 pVerifyPara
->cbSize
!= sizeof(CRYPT_VERIFY_MESSAGE_PARA
) ||
2495 GET_CMSG_ENCODING_TYPE(pVerifyPara
->dwMsgAndCertEncodingType
) !=
2496 PKCS_7_ASN_ENCODING
)
2498 SetLastError(E_INVALIDARG
);
2502 ret
= CryptDecodeObjectEx(pVerifyPara
->dwMsgAndCertEncodingType
,
2503 PKCS_CONTENT_INFO
, pbSignedBlob
, cbSignedBlob
,
2504 CRYPT_DECODE_ALLOC_FLAG
| CRYPT_DECODE_NOCOPY_FLAG
, NULL
,
2505 (LPBYTE
)&contentInfo
, &size
);
2508 if (strcmp(contentInfo
->pszObjId
, szOID_RSA_signedData
))
2510 SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE
);
2515 HCRYPTMSG msg
= CryptMsgOpenToDecode(
2516 pVerifyPara
->dwMsgAndCertEncodingType
, 0, CMSG_SIGNED
,
2517 pVerifyPara
->hCryptProv
, NULL
, NULL
);
2521 ret
= CryptMsgUpdate(msg
, contentInfo
->Content
.pbData
,
2522 contentInfo
->Content
.cbData
, TRUE
);
2523 if (ret
&& pcbDecoded
)
2524 ret
= CRYPT_CopyParam(pbDecoded
, pcbDecoded
,
2525 contentInfo
->Content
.pbData
, contentInfo
->Content
.cbData
);
2528 CERT_INFO
*certInfo
= CRYPT_GetSignerCertInfoFromMsg(msg
,
2534 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MSG
,
2535 pVerifyPara
->dwMsgAndCertEncodingType
,
2536 pVerifyPara
->hCryptProv
, 0, msg
);
2540 PCCERT_CONTEXT cert
= CRYPT_GetSignerCertificate(
2541 msg
, pVerifyPara
, certInfo
, store
);
2545 ret
= CryptMsgControl(msg
, 0,
2546 CMSG_CTRL_VERIFY_SIGNATURE
, cert
->pCertInfo
);
2547 if (ret
&& ppSignerCert
)
2548 *ppSignerCert
= cert
;
2550 CertFreeCertificateContext(cert
);
2552 CertCloseStore(store
, 0);
2555 CryptMemFree(certInfo
);
2560 LocalFree(contentInfo
);
2562 TRACE("returning %d\n", ret
);