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 const CDataEncodeMsg
*msg
= (const CDataEncodeMsg
*)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(msg
->base
.stream_info
.cbContent
, NULL
, &lenBytes
);
126 *pcbEncoded
= 1 + lenBytes
+ msg
->base
.stream_info
.cbContent
;
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(msg
->base
.stream_info
.cbContent
, 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 FIXME("unimplemented for indefinite-length encoding\n");
151 header
->pbData
= NULL
;
156 struct AsnConstructedItem constructed
= { 0, msg
,
157 CRYPT_EncodeContentLength
};
158 struct AsnEncodeSequenceItem items
[2] = {
159 { szOID_RSA_data
, CRYPT_AsnEncodeOid
, 0 },
160 { &constructed
, CRYPT_AsnEncodeConstructed
, 0 },
163 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
164 sizeof(items
) / sizeof(items
[0]), CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
165 (LPBYTE
)&header
->pbData
, &header
->cbData
);
168 /* Trick: subtract the content length from the reported length,
169 * as the actual content hasn't come yet.
171 header
->cbData
-= msg
->base
.stream_info
.cbContent
;
177 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
178 DWORD cbData
, BOOL fFinal
)
180 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
183 if (msg
->base
.streamed
)
187 if (msg
->base
.state
!= MsgStateUpdated
)
189 CRYPT_DATA_BLOB header
;
191 ret
= CRYPT_EncodeDataContentInfoHeader(msg
, &header
);
194 ret
= msg
->base
.stream_info
.pfnStreamOutput(
195 msg
->base
.stream_info
.pvArg
, header
.pbData
, header
.cbData
,
197 LocalFree(header
.pbData
);
201 ret
= msg
->base
.stream_info
.pfnStreamOutput(
202 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
206 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
208 BYTE indefinite_trailer
[6] = { 0 };
210 ret
= msg
->base
.stream_info
.pfnStreamOutput(
211 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
214 ret
= msg
->base
.stream_info
.pfnStreamOutput(
215 msg
->base
.stream_info
.pvArg
, indefinite_trailer
,
216 sizeof(indefinite_trailer
), TRUE
);
219 ret
= msg
->base
.stream_info
.pfnStreamOutput(
220 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
, TRUE
);
225 SetLastError(STATUS_ACCESS_VIOLATION
);
234 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
235 SetLastError(E_INVALIDARG
);
237 SetLastError(CRYPT_E_MSG_ERROR
);
242 SetLastError(E_INVALIDARG
);
245 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
247 /* non-streamed data messages don't allow non-final updates,
248 * don't bother checking whether data already exist, they can't.
250 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
251 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
252 &msg
->bare_content_len
);
259 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
266 else if (*pcbData
< len
)
269 SetLastError(ERROR_MORE_DATA
);
275 memcpy(pvData
, src
, len
);
280 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
281 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
283 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
288 case CMSG_CONTENT_PARAM
:
289 if (msg
->base
.streamed
)
290 SetLastError(E_INVALIDARG
);
293 CRYPT_CONTENT_INFO info
;
294 char rsa_data
[] = "1.2.840.113549.1.7.1";
296 info
.pszObjId
= rsa_data
;
297 info
.Content
.cbData
= msg
->bare_content_len
;
298 info
.Content
.pbData
= msg
->bare_content
;
299 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
303 case CMSG_BARE_CONTENT_PARAM
:
304 if (msg
->base
.streamed
)
305 SetLastError(E_INVALIDARG
);
307 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->bare_content
,
308 msg
->bare_content_len
);
311 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
316 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
317 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
323 SetLastError(E_INVALIDARG
);
326 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
329 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
330 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
,
331 CRYPT_DefaultMsgControl
);
332 msg
->bare_content_len
= sizeof(empty_data_content
);
333 msg
->bare_content
= (LPBYTE
)empty_data_content
;
335 return (HCRYPTMSG
)msg
;
338 typedef struct _CHashEncodeMsg
343 CRYPT_DATA_BLOB data
;
346 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
348 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
350 CryptMemFree(msg
->data
.pbData
);
351 CryptDestroyHash(msg
->hash
);
352 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
353 CryptReleaseContext(msg
->prov
, 0);
356 static BOOL
CRYPT_EncodePKCSDigestedData(CHashEncodeMsg
*msg
, void *pvData
,
361 DWORD size
= sizeof(algID
);
363 ret
= CryptGetHashParam(msg
->hash
, HP_ALGID
, (BYTE
*)&algID
, &size
, 0);
366 CRYPT_DIGESTED_DATA digestedData
= { 0 };
367 char oid_rsa_data
[] = szOID_RSA_data
;
369 digestedData
.version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
370 digestedData
.DigestAlgorithm
.pszObjId
= (LPSTR
)CertAlgIdToOID(algID
);
371 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
372 /* Quirk: OID is only encoded messages if an update has happened */
373 if (msg
->base
.state
!= MsgStateInit
)
374 digestedData
.ContentInfo
.pszObjId
= oid_rsa_data
;
375 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->data
.cbData
)
377 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &msg
->data
,
378 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
379 (LPBYTE
)&digestedData
.ContentInfo
.Content
.pbData
,
380 &digestedData
.ContentInfo
.Content
.cbData
);
382 if (msg
->base
.state
== MsgStateFinalized
)
384 size
= sizeof(DWORD
);
385 ret
= CryptGetHashParam(msg
->hash
, HP_HASHSIZE
,
386 (LPBYTE
)&digestedData
.hash
.cbData
, &size
, 0);
389 digestedData
.hash
.pbData
= CryptMemAlloc(
390 digestedData
.hash
.cbData
);
391 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
,
392 digestedData
.hash
.pbData
, &digestedData
.hash
.cbData
, 0);
396 ret
= CRYPT_AsnEncodePKCSDigestedData(&digestedData
, pvData
,
398 CryptMemFree(digestedData
.hash
.pbData
);
399 LocalFree(digestedData
.ContentInfo
.Content
.pbData
);
404 static BOOL
CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
405 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
407 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
410 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
415 case CMSG_BARE_CONTENT_PARAM
:
416 if (msg
->base
.streamed
)
417 SetLastError(E_INVALIDARG
);
419 ret
= CRYPT_EncodePKCSDigestedData(msg
, pvData
, pcbData
);
421 case CMSG_CONTENT_PARAM
:
423 CRYPT_CONTENT_INFO info
;
425 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
426 &info
.Content
.cbData
);
429 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
430 if (info
.Content
.pbData
)
432 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
433 info
.Content
.pbData
, &info
.Content
.cbData
);
436 char oid_rsa_hashed
[] = szOID_RSA_hashedData
;
438 info
.pszObjId
= oid_rsa_hashed
;
439 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
440 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
442 CryptMemFree(info
.Content
.pbData
);
449 case CMSG_COMPUTED_HASH_PARAM
:
450 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
, (BYTE
*)pvData
, pcbData
,
453 case CMSG_VERSION_PARAM
:
454 if (msg
->base
.state
!= MsgStateFinalized
)
455 SetLastError(CRYPT_E_MSG_ERROR
);
458 DWORD version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
460 /* Since the data are always encoded as octets, the version is
461 * always 0 (see rfc3852, section 7)
463 ret
= CRYPT_CopyParam(pvData
, pcbData
, &version
, sizeof(version
));
467 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
472 static BOOL
CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
473 DWORD cbData
, BOOL fFinal
)
475 CHashEncodeMsg
*msg
= (CHashEncodeMsg
*)hCryptMsg
;
478 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
480 if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
482 /* Doesn't do much, as stream output is never called, and you
483 * can't get the content.
485 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
490 SetLastError(CRYPT_E_MSG_ERROR
);
493 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
496 msg
->data
.pbData
= CryptMemAlloc(cbData
);
497 if (msg
->data
.pbData
)
499 memcpy(msg
->data
.pbData
+ msg
->data
.cbData
, pbData
, cbData
);
500 msg
->data
.cbData
+= cbData
;
510 static HCRYPTMSG
CHashEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
511 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
514 const CMSG_HASHED_ENCODE_INFO
*info
=
515 (const CMSG_HASHED_ENCODE_INFO
*)pvMsgEncodeInfo
;
519 if (info
->cbSize
!= sizeof(CMSG_HASHED_ENCODE_INFO
))
521 SetLastError(E_INVALIDARG
);
524 if (!(algID
= CertOIDToAlgId(info
->HashAlgorithm
.pszObjId
)))
526 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
529 if (info
->hCryptProv
)
530 prov
= info
->hCryptProv
;
533 prov
= CRYPT_GetDefaultProvider();
534 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
536 msg
= CryptMemAlloc(sizeof(CHashEncodeMsg
));
539 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
540 CHashEncodeMsg_Close
, CHashEncodeMsg_GetParam
, CHashEncodeMsg_Update
,
541 CRYPT_DefaultMsgControl
);
543 msg
->data
.cbData
= 0;
544 msg
->data
.pbData
= NULL
;
545 if (!CryptCreateHash(prov
, algID
, 0, 0, &msg
->hash
))
551 return (HCRYPTMSG
)msg
;
554 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
557 PCERT_INFO pCertInfo
;
558 HCRYPTPROV hCryptProv
;
560 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm
;
563 PCRYPT_ATTRIBUTE rgAuthAttr
;
565 PCRYPT_ATTRIBUTE rgUnauthAttr
;
567 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm
;
568 void *pvHashEncryptionAuxInfo
;
569 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS
;
571 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
575 PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners
;
577 PCERT_BLOB rgCertEncoded
;
579 PCRL_BLOB rgCrlEncoded
;
580 DWORD cAttrCertEncoded
;
581 PCERT_BLOB rgAttrCertEncoded
;
582 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS
;
584 static BOOL
CRYPT_IsValidSigner(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*signer
)
586 if (signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO
) &&
587 signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
589 SetLastError(E_INVALIDARG
);
592 if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
594 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
597 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
599 SetLastError(E_INVALIDARG
);
602 if (!signer
->pCertInfo
->Issuer
.cbData
)
604 SetLastError(E_INVALIDARG
);
607 if (!signer
->hCryptProv
)
609 SetLastError(E_INVALIDARG
);
612 if (!CertOIDToAlgId(signer
->HashAlgorithm
.pszObjId
))
614 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
620 static BOOL
CRYPT_ConstructBlob(CRYPT_DATA_BLOB
*out
, const CRYPT_DATA_BLOB
*in
)
624 out
->cbData
= in
->cbData
;
627 out
->pbData
= CryptMemAlloc(out
->cbData
);
629 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
638 typedef struct _BlobArray
641 PCRYPT_DATA_BLOB blobs
;
644 static BOOL
CRYPT_ConstructBlobArray(BlobArray
*out
, const BlobArray
*in
)
648 out
->cBlobs
= in
->cBlobs
;
651 out
->blobs
= CryptMemAlloc(out
->cBlobs
* sizeof(CRYPT_DATA_BLOB
));
656 memset(out
->blobs
, 0, out
->cBlobs
* sizeof(CRYPT_DATA_BLOB
));
657 for (i
= 0; ret
&& i
< out
->cBlobs
; i
++)
658 ret
= CRYPT_ConstructBlob(&out
->blobs
[i
], &in
->blobs
[i
]);
666 static void CRYPT_FreeBlobArray(BlobArray
*array
)
670 for (i
= 0; i
< array
->cBlobs
; i
++)
671 CryptMemFree(array
->blobs
[i
].pbData
);
672 CryptMemFree(array
->blobs
);
675 static BOOL
CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE
*out
,
676 const CRYPT_ATTRIBUTE
*in
)
680 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
683 strcpy(out
->pszObjId
, in
->pszObjId
);
684 ret
= CRYPT_ConstructBlobArray((BlobArray
*)&out
->cValue
,
685 (const BlobArray
*)&in
->cValue
);
692 static BOOL
CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES
*out
,
693 const CRYPT_ATTRIBUTES
*in
)
697 out
->cAttr
= in
->cAttr
;
700 out
->rgAttr
= CryptMemAlloc(out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
705 memset(out
->rgAttr
, 0, out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
706 for (i
= 0; ret
&& i
< out
->cAttr
; i
++)
707 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[i
], &in
->rgAttr
[i
]);
717 /* Constructs a CMSG_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
718 static BOOL
CSignerInfo_Construct(CMSG_SIGNER_INFO
*info
,
719 CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*in
)
723 /* Note: needs to change if CMS fields are supported */
724 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
725 ret
= CRYPT_ConstructBlob(&info
->Issuer
, &in
->pCertInfo
->Issuer
);
727 ret
= CRYPT_ConstructBlob(&info
->SerialNumber
,
728 &in
->pCertInfo
->SerialNumber
);
729 /* Assumption: algorithm IDs will point to static strings, not
730 * stack-based ones, so copying the pointer values is safe.
732 info
->HashAlgorithm
.pszObjId
= in
->HashAlgorithm
.pszObjId
;
734 ret
= CRYPT_ConstructBlob(&info
->HashAlgorithm
.Parameters
,
735 &in
->HashAlgorithm
.Parameters
);
736 memset(&info
->HashEncryptionAlgorithm
, 0,
737 sizeof(info
->HashEncryptionAlgorithm
));
739 ret
= CRYPT_ConstructAttributes(&info
->AuthAttrs
,
740 (CRYPT_ATTRIBUTES
*)&in
->cAuthAttr
);
742 ret
= CRYPT_ConstructAttributes(&info
->UnauthAttrs
,
743 (CRYPT_ATTRIBUTES
*)&in
->cUnauthAttr
);
747 static void CSignerInfo_Free(CMSG_SIGNER_INFO
*info
)
751 CryptMemFree(info
->Issuer
.pbData
);
752 CryptMemFree(info
->SerialNumber
.pbData
);
753 CryptMemFree(info
->HashAlgorithm
.Parameters
.pbData
);
754 CryptMemFree(info
->EncryptedHash
.pbData
);
755 for (i
= 0; i
< info
->AuthAttrs
.cAttr
; i
++)
757 for (j
= 0; j
< info
->AuthAttrs
.rgAttr
[i
].cValue
; j
++)
758 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
759 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
);
760 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].pszObjId
);
762 CryptMemFree(info
->AuthAttrs
.rgAttr
);
763 for (i
= 0; i
< info
->UnauthAttrs
.cAttr
; i
++)
765 for (j
= 0; j
< info
->UnauthAttrs
.rgAttr
[i
].cValue
; j
++)
766 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
767 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
);
768 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].pszObjId
);
770 CryptMemFree(info
->UnauthAttrs
.rgAttr
);
773 typedef struct _CSignerHandles
775 HCRYPTHASH contentHash
;
776 HCRYPTHASH authAttrHash
;
780 typedef struct _CSignedMsgData
782 CRYPT_SIGNED_INFO
*info
;
783 CSignerHandles
*signerHandles
;
786 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
787 * Assumes signerIndex is a valid idnex, and that msg_data's info has already
790 static BOOL
CSignedMsgData_ConstructSignerHandles(CSignedMsgData
*msg_data
,
791 DWORD signerIndex
, HCRYPTPROV crypt_prov
)
796 algID
= CertOIDToAlgId(
797 msg_data
->info
->rgSignerInfo
[signerIndex
].HashAlgorithm
.pszObjId
);
798 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
799 &msg_data
->signerHandles
->contentHash
);
800 if (ret
&& msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
> 0)
801 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
802 &msg_data
->signerHandles
->authAttrHash
);
806 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
809 static BOOL
CSignedMsgData_AllocateHandles(CSignedMsgData
*msg_data
)
813 if (msg_data
->info
->cSignerInfo
)
815 msg_data
->signerHandles
=
816 CryptMemAlloc(msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
817 if (msg_data
->signerHandles
)
818 memset(msg_data
->signerHandles
, 0,
819 msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
824 msg_data
->signerHandles
= NULL
;
828 static void CSignedMsgData_CloseHandles(CSignedMsgData
*msg_data
)
832 for (i
= 0; i
< msg_data
->info
->cSignerInfo
; i
++)
834 if (msg_data
->signerHandles
[i
].key
)
835 CryptDestroyKey(msg_data
->signerHandles
[i
].key
);
836 if (msg_data
->signerHandles
[i
].contentHash
)
837 CryptDestroyHash(msg_data
->signerHandles
[i
].contentHash
);
838 if (msg_data
->signerHandles
[i
].authAttrHash
)
839 CryptDestroyHash(msg_data
->signerHandles
[i
].authAttrHash
);
841 CryptMemFree(msg_data
->signerHandles
);
844 static BOOL
CSignedMsgData_UpdateHash(CSignedMsgData
*msg_data
,
845 const BYTE
*pbData
, DWORD cbData
)
850 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
851 ret
= CryptHashData(msg_data
->signerHandles
[i
].contentHash
, pbData
,
856 static BOOL
CRYPT_AppendAttribute(CRYPT_ATTRIBUTES
*out
,
857 const CRYPT_ATTRIBUTE
*in
)
861 out
->rgAttr
= CryptMemRealloc(out
->rgAttr
,
862 (out
->cAttr
+ 1) * sizeof(CRYPT_ATTRIBUTE
));
865 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[out
->cAttr
], in
);
872 static BOOL
CSignedMsgData_AppendMessageDigestAttribute(
873 CSignedMsgData
*msg_data
, DWORD signerIndex
)
877 CRYPT_HASH_BLOB hash
= { 0, NULL
}, encodedHash
= { 0, NULL
};
878 char messageDigest
[] = szOID_RSA_messageDigest
;
879 CRYPT_ATTRIBUTE messageDigestAttr
= { messageDigest
, 1, &encodedHash
};
881 size
= sizeof(DWORD
);
882 ret
= CryptGetHashParam(
883 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHSIZE
,
884 (LPBYTE
)&hash
.cbData
, &size
, 0);
887 hash
.pbData
= CryptMemAlloc(hash
.cbData
);
888 ret
= CryptGetHashParam(
889 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHVAL
,
890 hash
.pbData
, &hash
.cbData
, 0);
893 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &hash
, CRYPT_ENCODE_ALLOC_FLAG
,
894 NULL
, (LPBYTE
)&encodedHash
.pbData
, &encodedHash
.cbData
);
897 ret
= CRYPT_AppendAttribute(
898 &msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
,
900 LocalFree(encodedHash
.pbData
);
903 CryptMemFree(hash
.pbData
);
913 static BOOL
CSignedMsgData_UpdateAuthenticatedAttributes(
914 CSignedMsgData
*msg_data
, SignOrVerify flag
)
919 TRACE("(%p)\n", msg_data
);
921 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
923 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
927 BYTE oid_rsa_data_encoded
[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
928 0xf7,0x0d,0x01,0x07,0x01 };
929 CRYPT_DATA_BLOB content
= { sizeof(oid_rsa_data_encoded
),
930 oid_rsa_data_encoded
};
931 char contentType
[] = szOID_RSA_contentType
;
932 CRYPT_ATTRIBUTE contentTypeAttr
= { contentType
, 1, &content
};
934 /* FIXME: does this depend on inner OID? */
935 ret
= CRYPT_AppendAttribute(
936 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
, &contentTypeAttr
);
938 ret
= CSignedMsgData_AppendMessageDigestAttribute(msg_data
,
946 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, PKCS_ATTRIBUTES
,
947 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
,
948 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&encodedAttrs
, &size
);
952 msg_data
->signerHandles
[i
].authAttrHash
, encodedAttrs
,
954 LocalFree(encodedAttrs
);
959 TRACE("returning %d\n", ret
);
963 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB
*hash
)
968 for (i
= 0; i
< hash
->cbData
/ 2; i
++)
970 tmp
= hash
->pbData
[hash
->cbData
- i
- 1];
971 hash
->pbData
[hash
->cbData
- i
- 1] = hash
->pbData
[i
];
972 hash
->pbData
[i
] = tmp
;
976 static BOOL
CSignedMsgData_Sign(CSignedMsgData
*msg_data
)
981 TRACE("(%p)\n", msg_data
);
983 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
987 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
988 hash
= msg_data
->signerHandles
[i
].authAttrHash
;
990 hash
= msg_data
->signerHandles
[i
].contentHash
;
991 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0, NULL
,
992 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
995 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
=
997 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
998 if (msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
)
1000 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0,
1001 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
,
1002 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1005 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
);
1014 static BOOL
CSignedMsgData_Update(CSignedMsgData
*msg_data
,
1015 const BYTE
*pbData
, DWORD cbData
, BOOL fFinal
, SignOrVerify flag
)
1017 BOOL ret
= CSignedMsgData_UpdateHash(msg_data
, pbData
, cbData
);
1021 ret
= CSignedMsgData_UpdateAuthenticatedAttributes(msg_data
, flag
);
1022 if (ret
&& flag
== Sign
)
1023 ret
= CSignedMsgData_Sign(msg_data
);
1028 typedef struct _CSignedEncodeMsg
1031 CRYPT_DATA_BLOB data
;
1032 CSignedMsgData msg_data
;
1035 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1037 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1040 CryptMemFree(msg
->data
.pbData
);
1041 CRYPT_FreeBlobArray((BlobArray
*)&msg
->msg_data
.info
->cCertEncoded
);
1042 CRYPT_FreeBlobArray((BlobArray
*)&msg
->msg_data
.info
->cCrlEncoded
);
1043 for (i
= 0; i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1044 CSignerInfo_Free(&msg
->msg_data
.info
->rgSignerInfo
[i
]);
1045 CSignedMsgData_CloseHandles(&msg
->msg_data
);
1046 CryptMemFree(msg
->msg_data
.info
->rgSignerInfo
);
1047 CryptMemFree(msg
->msg_data
.info
);
1050 static BOOL
CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1051 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1053 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1056 switch (dwParamType
)
1058 case CMSG_CONTENT_PARAM
:
1060 CRYPT_CONTENT_INFO info
;
1062 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1063 &info
.Content
.cbData
);
1066 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1067 if (info
.Content
.pbData
)
1069 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1070 info
.Content
.pbData
, &info
.Content
.cbData
);
1073 char oid_rsa_signed
[] = szOID_RSA_signedData
;
1075 info
.pszObjId
= oid_rsa_signed
;
1076 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1077 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1079 CryptMemFree(info
.Content
.pbData
);
1086 case CMSG_BARE_CONTENT_PARAM
:
1088 CRYPT_SIGNED_INFO info
;
1089 char oid_rsa_data
[] = szOID_RSA_data
;
1091 memcpy(&info
, msg
->msg_data
.info
, sizeof(info
));
1092 /* Quirk: OID is only encoded messages if an update has happened */
1093 if (msg
->base
.state
!= MsgStateInit
)
1094 info
.content
.pszObjId
= oid_rsa_data
;
1096 info
.content
.pszObjId
= NULL
;
1097 if (msg
->data
.cbData
)
1099 CRYPT_DATA_BLOB blob
= { msg
->data
.cbData
, msg
->data
.pbData
};
1101 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1102 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
1103 &info
.content
.Content
.pbData
, &info
.content
.Content
.cbData
);
1107 info
.content
.Content
.cbData
= 0;
1108 info
.content
.Content
.pbData
= NULL
;
1113 ret
= CRYPT_AsnEncodePKCSSignedInfo(&info
, pvData
, pcbData
);
1114 LocalFree(info
.content
.Content
.pbData
);
1118 case CMSG_COMPUTED_HASH_PARAM
:
1119 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1120 SetLastError(CRYPT_E_INVALID_INDEX
);
1122 ret
= CryptGetHashParam(
1123 msg
->msg_data
.signerHandles
[dwIndex
].contentHash
, HP_HASHVAL
,
1124 pvData
, pcbData
, 0);
1126 case CMSG_ENCODED_SIGNER
:
1127 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1128 SetLastError(CRYPT_E_INVALID_INDEX
);
1130 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1131 PKCS7_SIGNER_INFO
, &msg
->msg_data
.info
->rgSignerInfo
[dwIndex
], 0,
1132 NULL
, pvData
, pcbData
);
1134 case CMSG_VERSION_PARAM
:
1135 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->msg_data
.info
->version
,
1136 sizeof(msg
->msg_data
.info
->version
));
1139 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1144 static BOOL
CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1145 DWORD cbData
, BOOL fFinal
)
1147 CSignedEncodeMsg
*msg
= (CSignedEncodeMsg
*)hCryptMsg
;
1150 if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1152 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
, fFinal
,
1154 if (msg
->base
.streamed
)
1155 FIXME("streamed partial stub\n");
1160 SetLastError(CRYPT_E_MSG_ERROR
);
1165 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1166 if (msg
->data
.pbData
)
1168 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1169 msg
->data
.cbData
= cbData
;
1176 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
,
1183 static HCRYPTMSG
CSignedEncodeMsg_Open(DWORD dwFlags
,
1184 const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
1185 PCMSG_STREAM_INFO pStreamInfo
)
1187 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*info
=
1188 (const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*)pvMsgEncodeInfo
;
1190 CSignedEncodeMsg
*msg
;
1192 if (info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO
) &&
1193 info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1195 SetLastError(E_INVALIDARG
);
1198 if (info
->cbSize
== sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1200 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1203 for (i
= 0; i
< info
->cSigners
; i
++)
1204 if (!CRYPT_IsValidSigner(&info
->rgSigners
[i
]))
1206 msg
= CryptMemAlloc(sizeof(CSignedEncodeMsg
));
1211 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1212 CSignedEncodeMsg_Close
, CSignedEncodeMsg_GetParam
,
1213 CSignedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1214 msg
->data
.cbData
= 0;
1215 msg
->data
.pbData
= NULL
;
1216 msg
->msg_data
.info
= CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO
));
1217 if (msg
->msg_data
.info
)
1219 memset(msg
->msg_data
.info
, 0, sizeof(CRYPT_SIGNED_INFO
));
1220 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V1
;
1224 if (ret
&& info
->cSigners
)
1226 msg
->msg_data
.info
->rgSignerInfo
=
1227 CryptMemAlloc(info
->cSigners
* sizeof(CMSG_SIGNER_INFO
));
1228 if (msg
->msg_data
.info
->rgSignerInfo
)
1230 msg
->msg_data
.info
->cSignerInfo
= info
->cSigners
;
1231 memset(msg
->msg_data
.info
->rgSignerInfo
, 0,
1232 msg
->msg_data
.info
->cSignerInfo
* sizeof(CMSG_SIGNER_INFO
));
1233 ret
= CSignedMsgData_AllocateHandles(&msg
->msg_data
);
1234 for (i
= 0; ret
&& i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1236 ret
= CSignerInfo_Construct(
1237 &msg
->msg_data
.info
->rgSignerInfo
[i
],
1238 &info
->rgSigners
[i
]);
1241 ret
= CSignedMsgData_ConstructSignerHandles(
1242 &msg
->msg_data
, i
, info
->rgSigners
[i
].hCryptProv
);
1243 if (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1244 CryptReleaseContext(info
->rgSigners
[i
].hCryptProv
,
1253 ret
= CRYPT_ConstructBlobArray(
1254 (BlobArray
*)&msg
->msg_data
.info
->cCertEncoded
,
1255 (const BlobArray
*)&info
->cCertEncoded
);
1257 ret
= CRYPT_ConstructBlobArray(
1258 (BlobArray
*)&msg
->msg_data
.info
->cCrlEncoded
,
1259 (const BlobArray
*)&info
->cCrlEncoded
);
1262 CSignedEncodeMsg_Close(msg
);
1269 static inline const char *MSG_TYPE_STR(DWORD type
)
1273 #define _x(x) case (x): return #x
1277 _x(CMSG_SIGNED_AND_ENVELOPED
);
1282 return wine_dbg_sprintf("unknown (%d)", type
);
1286 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
1287 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
1288 PCMSG_STREAM_INFO pStreamInfo
)
1290 HCRYPTMSG msg
= NULL
;
1292 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
1293 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
1295 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
1297 SetLastError(E_INVALIDARG
);
1303 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1304 pszInnerContentObjID
, pStreamInfo
);
1307 msg
= CHashEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1308 pszInnerContentObjID
, pStreamInfo
);
1311 msg
= CSignedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1312 pszInnerContentObjID
, pStreamInfo
);
1314 case CMSG_ENVELOPED
:
1315 FIXME("unimplemented for type %s\n", MSG_TYPE_STR(dwMsgType
));
1317 case CMSG_SIGNED_AND_ENVELOPED
:
1318 case CMSG_ENCRYPTED
:
1319 /* defined but invalid, fall through */
1321 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1326 typedef struct _CDecodeMsg
1330 HCRYPTPROV crypt_prov
;
1333 CSignedMsgData signed_data
;
1335 CRYPT_DATA_BLOB msg_data
;
1336 PCONTEXT_PROPERTY_LIST properties
;
1339 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg
)
1341 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
1343 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1344 CryptReleaseContext(msg
->crypt_prov
, 0);
1349 CryptDestroyHash(msg
->u
.hash
);
1352 if (msg
->u
.signed_data
.info
)
1354 LocalFree(msg
->u
.signed_data
.info
);
1355 CSignedMsgData_CloseHandles(&msg
->u
.signed_data
);
1359 CryptMemFree(msg
->msg_data
.pbData
);
1360 ContextPropertyList_Free(msg
->properties
);
1363 static BOOL
CDecodeMsg_CopyData(CDecodeMsg
*msg
, const BYTE
*pbData
,
1370 if (msg
->msg_data
.cbData
)
1371 msg
->msg_data
.pbData
= CryptMemRealloc(msg
->msg_data
.pbData
,
1372 msg
->msg_data
.cbData
+ cbData
);
1374 msg
->msg_data
.pbData
= CryptMemAlloc(cbData
);
1375 if (msg
->msg_data
.pbData
)
1377 memcpy(msg
->msg_data
.pbData
+ msg
->msg_data
.cbData
, pbData
, cbData
);
1378 msg
->msg_data
.cbData
+= cbData
;
1386 static BOOL
CDecodeMsg_DecodeDataContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
1389 CRYPT_DATA_BLOB
*data
;
1392 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1393 blob
->pbData
, blob
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&data
,
1397 ret
= ContextPropertyList_SetProperty(msg
->properties
,
1398 CMSG_CONTENT_PARAM
, data
->pbData
, data
->cbData
);
1404 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg
*msg
, DWORD param
,
1405 const CRYPT_ALGORITHM_IDENTIFIER
*id
)
1407 static const BYTE nullParams
[] = { ASN_NULL
, 0 };
1408 CRYPT_ALGORITHM_IDENTIFIER
*copy
;
1409 DWORD len
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
1411 /* Linearize algorithm id */
1412 len
+= strlen(id
->pszObjId
) + 1;
1413 len
+= id
->Parameters
.cbData
;
1414 copy
= CryptMemAlloc(len
);
1418 (LPSTR
)((BYTE
*)copy
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
1419 strcpy(copy
->pszObjId
, id
->pszObjId
);
1420 copy
->Parameters
.pbData
= (BYTE
*)copy
->pszObjId
+ strlen(id
->pszObjId
)
1422 /* Trick: omit NULL parameters */
1423 if (id
->Parameters
.cbData
== sizeof(nullParams
) &&
1424 !memcmp(id
->Parameters
.pbData
, nullParams
, sizeof(nullParams
)))
1426 copy
->Parameters
.cbData
= 0;
1427 len
-= sizeof(nullParams
);
1430 copy
->Parameters
.cbData
= id
->Parameters
.cbData
;
1431 if (copy
->Parameters
.cbData
)
1432 memcpy(copy
->Parameters
.pbData
, id
->Parameters
.pbData
,
1433 id
->Parameters
.cbData
);
1434 ContextPropertyList_SetProperty(msg
->properties
, param
, (BYTE
*)copy
,
1440 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER
*id
)
1442 id
->pszObjId
= (LPSTR
)((BYTE
*)id
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
1443 id
->Parameters
.pbData
= (BYTE
*)id
->pszObjId
+ strlen(id
->pszObjId
) + 1;
1446 static BOOL
CDecodeMsg_DecodeHashedContent(CDecodeMsg
*msg
,
1447 CRYPT_DER_BLOB
*blob
)
1450 CRYPT_DIGESTED_DATA
*digestedData
;
1453 ret
= CRYPT_AsnDecodePKCSDigestedData(blob
->pbData
, blob
->cbData
,
1454 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_DIGESTED_DATA
*)&digestedData
,
1458 ContextPropertyList_SetProperty(msg
->properties
, CMSG_VERSION_PARAM
,
1459 (const BYTE
*)&digestedData
->version
, sizeof(digestedData
->version
));
1460 CDecodeMsg_SaveAlgorithmID(msg
, CMSG_HASH_ALGORITHM_PARAM
,
1461 &digestedData
->DigestAlgorithm
);
1462 ContextPropertyList_SetProperty(msg
->properties
,
1463 CMSG_INNER_CONTENT_TYPE_PARAM
,
1464 (const BYTE
*)digestedData
->ContentInfo
.pszObjId
,
1465 digestedData
->ContentInfo
.pszObjId
?
1466 strlen(digestedData
->ContentInfo
.pszObjId
) + 1 : 0);
1467 if (digestedData
->ContentInfo
.Content
.cbData
)
1468 CDecodeMsg_DecodeDataContent(msg
,
1469 &digestedData
->ContentInfo
.Content
);
1471 ContextPropertyList_SetProperty(msg
->properties
,
1472 CMSG_CONTENT_PARAM
, NULL
, 0);
1473 ContextPropertyList_SetProperty(msg
->properties
, CMSG_HASH_DATA_PARAM
,
1474 digestedData
->hash
.pbData
, digestedData
->hash
.cbData
);
1475 LocalFree(digestedData
);
1480 static BOOL
CDecodeMsg_DecodeSignedContent(CDecodeMsg
*msg
,
1481 CRYPT_DER_BLOB
*blob
)
1484 CRYPT_SIGNED_INFO
*signedInfo
;
1487 ret
= CRYPT_AsnDecodePKCSSignedInfo(blob
->pbData
, blob
->cbData
,
1488 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_SIGNED_INFO
*)&signedInfo
,
1494 msg
->u
.signed_data
.info
= signedInfo
;
1495 ret
= CSignedMsgData_AllocateHandles(&msg
->u
.signed_data
);
1496 for (i
= 0; ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
1497 ret
= CSignedMsgData_ConstructSignerHandles(&msg
->u
.signed_data
, i
,
1501 /* Now that we have all the content, update the hash handles with
1502 * it. Have to decode it if the type is szOID_RSA_data.
1504 if (msg
->u
.signed_data
.info
->content
.Content
.cbData
)
1506 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
1509 CRYPT_DATA_BLOB
*blob
;
1511 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
,
1513 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
1514 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
1515 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&blob
, &size
);
1518 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
1519 blob
->pbData
, blob
->cbData
, TRUE
, Verify
);
1524 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
1525 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
1526 msg
->u
.signed_data
.info
->content
.Content
.cbData
, TRUE
,
1533 /* Decodes the content in blob as the type given, and updates the value
1534 * (type, parameters, etc.) of msg based on what blob contains.
1535 * It doesn't just use msg's type, to allow a recursive call from an implicitly
1536 * typed message once the outer content info has been decoded.
1538 static BOOL
CDecodeMsg_DecodeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
,
1546 if ((ret
= CDecodeMsg_DecodeDataContent(msg
, blob
)))
1547 msg
->type
= CMSG_DATA
;
1550 if ((ret
= CDecodeMsg_DecodeHashedContent(msg
, blob
)))
1551 msg
->type
= CMSG_HASHED
;
1553 case CMSG_ENVELOPED
:
1554 FIXME("unimplemented for type %s\n", MSG_TYPE_STR(type
));
1558 if ((ret
= CDecodeMsg_DecodeSignedContent(msg
, blob
)))
1559 msg
->type
= CMSG_SIGNED
;
1563 CRYPT_CONTENT_INFO
*info
;
1566 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
,
1567 msg
->msg_data
.pbData
, msg
->msg_data
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
1568 NULL
, (LPBYTE
)&info
, &size
);
1571 if (!strcmp(info
->pszObjId
, szOID_RSA_data
))
1572 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
, CMSG_DATA
);
1573 else if (!strcmp(info
->pszObjId
, szOID_RSA_digestedData
))
1574 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1576 else if (!strcmp(info
->pszObjId
, szOID_RSA_envelopedData
))
1577 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1579 else if (!strcmp(info
->pszObjId
, szOID_RSA_signedData
))
1580 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
1584 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1594 static BOOL
CDecodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1595 DWORD cbData
, BOOL fFinal
)
1597 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
1600 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
1602 if (msg
->base
.streamed
)
1604 ret
= CDecodeMsg_CopyData(msg
, pbData
, cbData
);
1605 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg
, pbData
,
1611 SetLastError(CRYPT_E_MSG_ERROR
);
1614 ret
= CDecodeMsg_CopyData(msg
, pbData
, cbData
);
1616 ret
= CDecodeMsg_DecodeContent(msg
, &msg
->msg_data
, msg
->type
);
1623 static BOOL
CDecodeHashMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
1624 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1628 switch (dwParamType
)
1630 case CMSG_TYPE_PARAM
:
1631 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
1633 case CMSG_HASH_ALGORITHM_PARAM
:
1635 CRYPT_DATA_BLOB blob
;
1637 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
1641 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
1643 CRYPT_FixUpAlgorithmID((CRYPT_ALGORITHM_IDENTIFIER
*)pvData
);
1646 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1649 case CMSG_COMPUTED_HASH_PARAM
:
1652 CRYPT_ALGORITHM_IDENTIFIER
*hashAlgoID
= NULL
;
1656 CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, NULL
, &size
);
1657 hashAlgoID
= CryptMemAlloc(size
);
1658 ret
= CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0,
1661 algID
= CertOIDToAlgId(hashAlgoID
->pszObjId
);
1662 ret
= CryptCreateHash(msg
->crypt_prov
, algID
, 0, 0, &msg
->u
.hash
);
1665 CRYPT_DATA_BLOB content
;
1667 ret
= ContextPropertyList_FindProperty(msg
->properties
,
1668 CMSG_CONTENT_PARAM
, &content
);
1670 ret
= CryptHashData(msg
->u
.hash
, content
.pbData
,
1673 CryptMemFree(hashAlgoID
);
1678 ret
= CryptGetHashParam(msg
->u
.hash
, HP_HASHVAL
, pvData
, pcbData
,
1683 CRYPT_DATA_BLOB blob
;
1685 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
1688 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
1690 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1696 /* nextData is an in/out parameter - on input it's the memory location in
1697 * which a copy of in's data should be made, and on output it's the memory
1698 * location immediately after out's copy of in's data.
1700 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB
*out
,
1701 const CRYPT_DATA_BLOB
*in
, LPBYTE
*nextData
)
1703 out
->cbData
= in
->cbData
;
1706 out
->pbData
= *nextData
;
1707 memcpy(out
->pbData
, in
->pbData
, in
->cbData
);
1708 *nextData
+= in
->cbData
;
1712 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
1713 const CRYPT_ALGORITHM_IDENTIFIER
*in
, LPBYTE
*nextData
)
1717 out
->pszObjId
= (LPSTR
)*nextData
;
1718 strcpy(out
->pszObjId
, in
->pszObjId
);
1719 *nextData
+= strlen(out
->pszObjId
) + 1;
1721 CRYPT_CopyBlob(&out
->Parameters
, &in
->Parameters
, nextData
);
1724 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES
*out
,
1725 const CRYPT_ATTRIBUTES
*in
, LPBYTE
*nextData
)
1727 out
->cAttr
= in
->cAttr
;
1732 if ((*nextData
- (LPBYTE
)0) % sizeof(DWORD
))
1733 *nextData
+= (*nextData
- (LPBYTE
)0) % sizeof(DWORD
);
1734 out
->rgAttr
= (CRYPT_ATTRIBUTE
*)*nextData
;
1735 *nextData
+= in
->cAttr
* sizeof(CRYPT_ATTRIBUTE
);
1736 for (i
= 0; i
< in
->cAttr
; i
++)
1738 if (in
->rgAttr
[i
].pszObjId
)
1740 out
->rgAttr
[i
].pszObjId
= (LPSTR
)*nextData
;
1741 strcpy(out
->rgAttr
[i
].pszObjId
, in
->rgAttr
[i
].pszObjId
);
1742 *nextData
+= strlen(in
->rgAttr
[i
].pszObjId
) + 1;
1744 if (in
->rgAttr
[i
].cValue
)
1748 out
->rgAttr
[i
].cValue
= in
->rgAttr
[i
].cValue
;
1749 if ((*nextData
- (LPBYTE
)0) % sizeof(DWORD
))
1750 *nextData
+= (*nextData
- (LPBYTE
)0) % sizeof(DWORD
);
1751 out
->rgAttr
[i
].rgValue
= (PCRYPT_DATA_BLOB
)*nextData
;
1752 for (j
= 0; j
< in
->rgAttr
[i
].cValue
; j
++)
1753 CRYPT_CopyBlob(&out
->rgAttr
[i
].rgValue
[j
],
1754 &in
->rgAttr
[i
].rgValue
[j
], nextData
);
1760 static DWORD
CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES
*attr
)
1762 DWORD size
= attr
->cAttr
* sizeof(CRYPT_ATTRIBUTE
), i
, j
;
1764 for (i
= 0; i
< attr
->cAttr
; i
++)
1766 if (attr
->rgAttr
[i
].pszObjId
)
1767 size
+= strlen(attr
->rgAttr
[i
].pszObjId
) + 1;
1769 if (size
% sizeof(DWORD
))
1770 size
+= size
% sizeof(DWORD
);
1771 size
+= attr
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
1772 for (j
= 0; j
< attr
->rgAttr
[i
].cValue
; j
++)
1773 size
+= attr
->rgAttr
[i
].rgValue
[j
].cbData
;
1778 static BOOL
CRYPT_CopySignerInfo(void *pvData
, DWORD
*pcbData
,
1779 const CMSG_SIGNER_INFO
*in
)
1781 DWORD size
= sizeof(CMSG_SIGNER_INFO
);
1784 size
+= in
->Issuer
.cbData
;
1785 size
+= in
->SerialNumber
.cbData
;
1786 if (in
->HashAlgorithm
.pszObjId
)
1787 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
1788 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
1789 if (in
->HashEncryptionAlgorithm
.pszObjId
)
1790 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
1791 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
1792 size
+= in
->EncryptedHash
.cbData
;
1794 if (size
% sizeof(DWORD
))
1795 size
+= size
% sizeof(DWORD
);
1796 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
1797 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
1803 else if (*pcbData
< size
)
1806 SetLastError(ERROR_MORE_DATA
);
1811 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_SIGNER_INFO
);
1812 CMSG_SIGNER_INFO
*out
= (CMSG_SIGNER_INFO
*)pvData
;
1814 out
->dwVersion
= in
->dwVersion
;
1815 CRYPT_CopyBlob(&out
->Issuer
, &in
->Issuer
, &nextData
);
1816 CRYPT_CopyBlob(&out
->SerialNumber
, &in
->SerialNumber
, &nextData
);
1817 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
1819 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
1820 &in
->HashEncryptionAlgorithm
, &nextData
);
1821 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
1823 if ((nextData
- (LPBYTE
)0) % sizeof(DWORD
))
1824 nextData
+= (nextData
- (LPBYTE
)0) % sizeof(DWORD
);
1825 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
1826 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
1832 static BOOL
CRYPT_CopySignerCertInfo(void *pvData
, DWORD
*pcbData
,
1833 const CMSG_SIGNER_INFO
*in
)
1835 DWORD size
= sizeof(CERT_INFO
);
1838 size
+= in
->Issuer
.cbData
;
1839 size
+= in
->SerialNumber
.cbData
;
1845 else if (*pcbData
< size
)
1848 SetLastError(ERROR_MORE_DATA
);
1853 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
1854 CERT_INFO
*out
= (CERT_INFO
*)pvData
;
1856 memset(out
, 0, sizeof(CERT_INFO
));
1857 CRYPT_CopyBlob(&out
->Issuer
, &in
->Issuer
, &nextData
);
1858 CRYPT_CopyBlob(&out
->SerialNumber
, &in
->SerialNumber
, &nextData
);
1864 static BOOL
CDecodeSignedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
1865 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1869 switch (dwParamType
)
1871 case CMSG_TYPE_PARAM
:
1872 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
1874 case CMSG_CONTENT_PARAM
:
1875 if (msg
->u
.signed_data
.info
)
1877 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
1880 CRYPT_DATA_BLOB
*blob
;
1883 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1884 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
1885 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
1886 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&blob
, &size
);
1889 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
->pbData
,
1895 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1896 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
1897 msg
->u
.signed_data
.info
->content
.Content
.cbData
);
1900 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1902 case CMSG_INNER_CONTENT_TYPE_PARAM
:
1903 if (msg
->u
.signed_data
.info
)
1904 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1905 msg
->u
.signed_data
.info
->content
.pszObjId
,
1906 strlen(msg
->u
.signed_data
.info
->content
.pszObjId
) + 1);
1908 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1910 case CMSG_SIGNER_COUNT_PARAM
:
1911 if (msg
->u
.signed_data
.info
)
1912 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1913 &msg
->u
.signed_data
.info
->cSignerInfo
, sizeof(DWORD
));
1915 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1917 case CMSG_SIGNER_INFO_PARAM
:
1918 if (msg
->u
.signed_data
.info
)
1920 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
1921 SetLastError(CRYPT_E_INVALID_INDEX
);
1923 ret
= CRYPT_CopySignerInfo(pvData
, pcbData
,
1924 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
1927 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1929 case CMSG_SIGNER_CERT_INFO_PARAM
:
1930 if (msg
->u
.signed_data
.info
)
1932 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
1933 SetLastError(CRYPT_E_INVALID_INDEX
);
1935 ret
= CRYPT_CopySignerCertInfo(pvData
, pcbData
,
1936 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
1939 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1941 case CMSG_CERT_COUNT_PARAM
:
1942 if (msg
->u
.signed_data
.info
)
1943 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1944 &msg
->u
.signed_data
.info
->cCertEncoded
, sizeof(DWORD
));
1946 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1948 case CMSG_CERT_PARAM
:
1949 if (msg
->u
.signed_data
.info
)
1951 if (dwIndex
>= msg
->u
.signed_data
.info
->cCertEncoded
)
1952 SetLastError(CRYPT_E_INVALID_INDEX
);
1954 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1955 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].pbData
,
1956 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].cbData
);
1959 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1961 case CMSG_CRL_COUNT_PARAM
:
1962 if (msg
->u
.signed_data
.info
)
1963 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1964 &msg
->u
.signed_data
.info
->cCrlEncoded
, sizeof(DWORD
));
1966 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1968 case CMSG_CRL_PARAM
:
1969 if (msg
->u
.signed_data
.info
)
1971 if (dwIndex
>= msg
->u
.signed_data
.info
->cCrlEncoded
)
1972 SetLastError(CRYPT_E_INVALID_INDEX
);
1974 ret
= CRYPT_CopyParam(pvData
, pcbData
,
1975 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].pbData
,
1976 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].cbData
);
1979 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1981 case CMSG_COMPUTED_HASH_PARAM
:
1982 if (msg
->u
.signed_data
.info
)
1984 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
1985 SetLastError(CRYPT_E_INVALID_INDEX
);
1987 ret
= CryptGetHashParam(
1988 msg
->u
.signed_data
.signerHandles
[dwIndex
].contentHash
,
1989 HP_HASHVAL
, pvData
, pcbData
, 0);
1992 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1994 case CMSG_ATTR_CERT_COUNT_PARAM
:
1995 if (msg
->u
.signed_data
.info
)
1997 DWORD attrCertCount
= 0;
1999 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2000 &attrCertCount
, sizeof(DWORD
));
2003 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2005 case CMSG_ATTR_CERT_PARAM
:
2006 if (msg
->u
.signed_data
.info
)
2007 SetLastError(CRYPT_E_INVALID_INDEX
);
2009 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2012 FIXME("unimplemented for %d\n", dwParamType
);
2013 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2018 static BOOL
CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
2019 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2021 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
2027 ret
= CDecodeHashMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2031 ret
= CDecodeSignedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2035 switch (dwParamType
)
2037 case CMSG_TYPE_PARAM
:
2038 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
,
2043 CRYPT_DATA_BLOB blob
;
2045 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2048 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
,
2051 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2058 static BOOL
CDecodeHashMsg_VerifyHash(CDecodeMsg
*msg
)
2061 CRYPT_DATA_BLOB hashBlob
;
2063 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2064 CMSG_HASH_DATA_PARAM
, &hashBlob
);
2067 DWORD computedHashSize
= 0;
2069 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
,
2071 if (hashBlob
.cbData
== computedHashSize
)
2073 LPBYTE computedHash
= CryptMemAlloc(computedHashSize
);
2077 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
2078 computedHash
, &computedHashSize
);
2080 ret
= !memcmp(hashBlob
.pbData
, computedHash
,
2090 static BOOL
CDecodeSignedMsg_VerifySignature(CDecodeMsg
*msg
, PCERT_INFO info
)
2095 for (i
= 0; !ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
2097 ret
= CertCompareCertificateName(X509_ASN_ENCODING
,
2098 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
].Issuer
, &info
->Issuer
);
2101 ret
= CertCompareIntegerBlob(
2102 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
].SerialNumber
,
2103 &info
->SerialNumber
);
2112 ret
= CryptImportPublicKeyInfo(msg
->crypt_prov
, X509_ASN_ENCODING
,
2113 &info
->SubjectPublicKeyInfo
, &key
);
2117 CRYPT_HASH_BLOB reversedHash
;
2119 if (msg
->u
.signed_data
.info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
2120 hash
= msg
->u
.signed_data
.signerHandles
[i
].authAttrHash
;
2122 hash
= msg
->u
.signed_data
.signerHandles
[i
].contentHash
;
2123 ret
= CRYPT_ConstructBlob(&reversedHash
,
2124 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
].EncryptedHash
);
2127 CRYPT_ReverseBytes(&reversedHash
);
2128 ret
= CryptVerifySignatureW(hash
, reversedHash
.pbData
,
2129 reversedHash
.cbData
, key
, NULL
, 0);
2130 CryptMemFree(reversedHash
.pbData
);
2132 CryptDestroyKey(key
);
2136 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
2141 static BOOL
CDecodeMsg_Control(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
2142 DWORD dwCtrlType
, const void *pvCtrlPara
)
2144 CDecodeMsg
*msg
= (CDecodeMsg
*)hCryptMsg
;
2149 case CMSG_CTRL_VERIFY_SIGNATURE
:
2153 ret
= CDecodeSignedMsg_VerifySignature(msg
, (PCERT_INFO
)pvCtrlPara
);
2156 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2159 case CMSG_CTRL_DECRYPT
:
2163 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2166 case CMSG_CTRL_VERIFY_HASH
:
2170 ret
= CDecodeHashMsg_VerifyHash(msg
);
2173 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2177 SetLastError(CRYPT_E_CONTROL_TYPE
);
2182 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
2183 DWORD dwMsgType
, HCRYPTPROV_LEGACY hCryptProv
, PCERT_INFO pRecipientInfo
,
2184 PCMSG_STREAM_INFO pStreamInfo
)
2188 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType
,
2189 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
2191 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
2193 SetLastError(E_INVALIDARG
);
2196 msg
= CryptMemAlloc(sizeof(CDecodeMsg
));
2199 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
2200 CDecodeMsg_Close
, CDecodeMsg_GetParam
, CDecodeMsg_Update
,
2201 CDecodeMsg_Control
);
2202 msg
->type
= dwMsgType
;
2204 msg
->crypt_prov
= hCryptProv
;
2207 msg
->crypt_prov
= CRYPT_GetDefaultProvider();
2208 msg
->base
.open_flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
2210 memset(&msg
->u
, 0, sizeof(msg
->u
));
2211 msg
->msg_data
.cbData
= 0;
2212 msg
->msg_data
.pbData
= NULL
;
2213 msg
->properties
= ContextPropertyList_Create();
2218 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
2220 TRACE("(%p)\n", hCryptMsg
);
2224 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2226 InterlockedIncrement(&msg
->ref
);
2231 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
2233 TRACE("(%p)\n", hCryptMsg
);
2237 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2239 if (InterlockedDecrement(&msg
->ref
) == 0)
2241 TRACE("freeing %p\n", msg
);
2250 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
2251 DWORD cbData
, BOOL fFinal
)
2253 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2256 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
2258 if (msg
->state
== MsgStateFinalized
)
2259 SetLastError(CRYPT_E_MSG_ERROR
);
2262 ret
= msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
2263 msg
->state
= MsgStateUpdated
;
2265 msg
->state
= MsgStateFinalized
;
2270 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
2271 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2273 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2275 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
2277 return msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);
2280 BOOL WINAPI
CryptMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
2281 DWORD dwCtrlType
, const void *pvCtrlPara
)
2283 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
2285 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
,
2287 return msg
->control(hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
2290 HCERTSTORE WINAPI
CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType
,
2291 HCRYPTPROV_LEGACY hCryptProv
, DWORD dwFlags
, const BYTE
* pbSignedBlob
,
2294 CRYPT_DATA_BLOB blob
= { cbSignedBlob
, (LPBYTE
)pbSignedBlob
};
2296 TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType
, hCryptProv
,
2297 dwFlags
, pbSignedBlob
, cbSignedBlob
);
2299 return CertOpenStore(CERT_STORE_PROV_PKCS7
, dwMsgAndCertEncodingType
,
2300 hCryptProv
, dwFlags
, &blob
);
2303 LONG WINAPI
CryptGetMessageSignerCount(DWORD dwMsgEncodingType
,
2304 const BYTE
*pbSignedBlob
, DWORD cbSignedBlob
)
2309 TRACE("(%08x, %p, %d)\n", dwMsgEncodingType
, pbSignedBlob
, cbSignedBlob
);
2311 msg
= CryptMsgOpenToDecode(dwMsgEncodingType
, 0, 0, 0, NULL
, NULL
);
2314 if (CryptMsgUpdate(msg
, pbSignedBlob
, cbSignedBlob
, TRUE
))
2316 DWORD size
= sizeof(count
);
2318 CryptMsgGetParam(msg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
, &size
);
2325 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
2326 DWORD dwSignerIndex
)
2328 CERT_INFO
*certInfo
= NULL
;
2331 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
2334 certInfo
= CryptMemAlloc(size
);
2337 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
2338 dwSignerIndex
, certInfo
, &size
))
2340 CryptMemFree(certInfo
);
2348 static PCCERT_CONTEXT WINAPI
CRYPT_DefaultGetSignerCertificate(void *pvGetArg
,
2349 DWORD dwCertEncodingType
, PCERT_INFO pSignerId
, HCERTSTORE hMsgCertStore
)
2351 return CertFindCertificateInStore(hMsgCertStore
, dwCertEncodingType
, 0,
2352 CERT_FIND_SUBJECT_CERT
, pSignerId
, NULL
);
2355 static inline PCCERT_CONTEXT
CRYPT_GetSignerCertificate(HCRYPTMSG msg
,
2356 PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara
, PCERT_INFO certInfo
, HCERTSTORE store
)
2358 PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert
;
2360 if (pVerifyPara
->pfnGetSignerCertificate
)
2361 getCert
= pVerifyPara
->pfnGetSignerCertificate
;
2363 getCert
= CRYPT_DefaultGetSignerCertificate
;
2364 return getCert(pVerifyPara
->pvGetArg
,
2365 pVerifyPara
->dwMsgAndCertEncodingType
, certInfo
, store
);
2368 BOOL WINAPI
CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara
,
2369 DWORD dwSignerIndex
, const BYTE
* pbSignedBlob
, DWORD cbSignedBlob
,
2370 BYTE
* pbDecoded
, DWORD
* pcbDecoded
, PCCERT_CONTEXT
* ppSignerCert
)
2374 CRYPT_CONTENT_INFO
*contentInfo
;
2376 TRACE("(%p, %d, %p, %d, %p, %p, %p)\n",
2377 pVerifyPara
, dwSignerIndex
, pbSignedBlob
, cbSignedBlob
,
2378 pbDecoded
, pcbDecoded
, ppSignerCert
);
2381 *ppSignerCert
= NULL
;
2385 pVerifyPara
->cbSize
!= sizeof(CRYPT_VERIFY_MESSAGE_PARA
) ||
2386 GET_CMSG_ENCODING_TYPE(pVerifyPara
->dwMsgAndCertEncodingType
) !=
2387 PKCS_7_ASN_ENCODING
)
2389 SetLastError(E_INVALIDARG
);
2393 ret
= CryptDecodeObjectEx(pVerifyPara
->dwMsgAndCertEncodingType
,
2394 PKCS_CONTENT_INFO
, pbSignedBlob
, cbSignedBlob
,
2395 CRYPT_DECODE_ALLOC_FLAG
| CRYPT_DECODE_NOCOPY_FLAG
, NULL
,
2396 (LPBYTE
)&contentInfo
, &size
);
2399 if (strcmp(contentInfo
->pszObjId
, szOID_RSA_signedData
))
2401 SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE
);
2406 HCRYPTMSG msg
= CryptMsgOpenToDecode(
2407 pVerifyPara
->dwMsgAndCertEncodingType
, 0, CMSG_SIGNED
,
2408 pVerifyPara
->hCryptProv
, NULL
, NULL
);
2412 ret
= CryptMsgUpdate(msg
, contentInfo
->Content
.pbData
,
2413 contentInfo
->Content
.cbData
, TRUE
);
2414 if (ret
&& pcbDecoded
)
2415 ret
= CRYPT_CopyParam(pbDecoded
, pcbDecoded
,
2416 contentInfo
->Content
.pbData
, contentInfo
->Content
.cbData
);
2419 CERT_INFO
*certInfo
= CRYPT_GetSignerCertInfoFromMsg(msg
,
2425 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MSG
,
2426 pVerifyPara
->dwMsgAndCertEncodingType
,
2427 pVerifyPara
->hCryptProv
, 0, msg
);
2431 PCCERT_CONTEXT cert
= CRYPT_GetSignerCertificate(
2432 msg
, pVerifyPara
, certInfo
, store
);
2436 ret
= CryptMsgControl(msg
, 0,
2437 CMSG_CTRL_VERIFY_SIGNATURE
, cert
->pCertInfo
);
2438 if (ret
&& ppSignerCert
)
2439 *ppSignerCert
= cert
;
2441 CertFreeCertificateContext(cert
);
2443 CertCloseStore(store
, 0);
2446 CryptMemFree(certInfo
);
2451 LocalFree(contentInfo
);
2453 TRACE("returning %d\n", ret
);