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
26 #include "wine/debug.h"
27 #include "wine/exception.h"
28 #include "crypt32_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
32 /* Called when a message's ref count reaches zero. Free any message-specific
35 typedef void (*CryptMsgCloseFunc
)(HCRYPTMSG msg
);
37 typedef BOOL (*CryptMsgGetParamFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
38 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
);
40 typedef BOOL (*CryptMsgUpdateFunc
)(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
41 DWORD cbData
, BOOL fFinal
);
43 typedef BOOL (*CryptMsgControlFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
44 DWORD dwCtrlType
, const void *pvCtrlPara
);
46 static BOOL
extract_hash(HCRYPTHASH hash
, BYTE
**data
, DWORD
*size
)
52 if (!CryptGetHashParam(hash
, HP_HASHSIZE
, (BYTE
*)size
, &sz
, 0)) return FALSE
;
53 if (!(*data
= CryptMemAlloc(*size
)))
58 if (CryptGetHashParam(hash
, HP_HASHVAL
, *data
, size
, 0)) return TRUE
;
64 static BOOL
CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
65 DWORD dwCtrlType
, const void *pvCtrlPara
)
67 TRACE("(%p, %08lx, %ld, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
68 SetLastError(E_INVALIDARG
);
72 typedef enum _CryptMsgState
{
75 MsgStateDataFinalized
,
79 typedef struct _CryptMsgBase
84 CMSG_STREAM_INFO stream_info
;
86 CryptMsgCloseFunc close
;
87 CryptMsgUpdateFunc update
;
88 CryptMsgGetParamFunc get_param
;
89 CryptMsgControlFunc control
;
92 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
93 PCMSG_STREAM_INFO pStreamInfo
, CryptMsgCloseFunc close
,
94 CryptMsgGetParamFunc get_param
, CryptMsgUpdateFunc update
,
95 CryptMsgControlFunc control
)
98 msg
->open_flags
= dwFlags
;
101 msg
->streamed
= TRUE
;
102 msg
->stream_info
= *pStreamInfo
;
106 msg
->streamed
= FALSE
;
107 memset(&msg
->stream_info
, 0, sizeof(msg
->stream_info
));
110 msg
->get_param
= get_param
;
111 msg
->update
= update
;
112 msg
->control
= control
;
113 msg
->state
= MsgStateInit
;
116 typedef struct _CDataEncodeMsg
119 DWORD bare_content_len
;
123 static const BYTE empty_data_content
[] = { 0x04,0x00 };
125 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
127 CDataEncodeMsg
*msg
= hCryptMsg
;
129 if (msg
->bare_content
!= empty_data_content
)
130 LocalFree(msg
->bare_content
);
133 static BOOL WINAPI
CRYPT_EncodeContentLength(DWORD dwCertEncodingType
,
134 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
135 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
137 DWORD dataLen
= *(DWORD
*)pvStructInfo
;
141 /* Trick: report bytes needed based on total message length, even though
142 * the message isn't available yet. The caller will use the length
143 * reported here to encode its length.
145 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
147 *pcbEncoded
= 1 + lenBytes
+ dataLen
;
150 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
151 pcbEncoded
, 1 + lenBytes
)))
153 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
154 pbEncoded
= *(BYTE
**)pbEncoded
;
155 *pbEncoded
++ = ASN_OCTETSTRING
;
156 CRYPT_EncodeLen(dataLen
, pbEncoded
,
163 static BOOL
CRYPT_EncodeDataContentInfoHeader(const CDataEncodeMsg
*msg
,
164 CRYPT_DATA_BLOB
*header
)
168 if (msg
->base
.streamed
&& msg
->base
.stream_info
.cbContent
== 0xffffffff)
170 static const BYTE headerValue
[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
171 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
173 header
->pbData
= LocalAlloc(0, sizeof(headerValue
));
176 header
->cbData
= sizeof(headerValue
);
177 memcpy(header
->pbData
, headerValue
, sizeof(headerValue
));
185 struct AsnConstructedItem constructed
= { 0,
186 &msg
->base
.stream_info
.cbContent
, CRYPT_EncodeContentLength
};
187 struct AsnEncodeSequenceItem items
[2] = {
188 { szOID_RSA_data
, CRYPT_AsnEncodeOid
, 0 },
189 { &constructed
, CRYPT_AsnEncodeConstructed
, 0 },
192 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
193 ARRAY_SIZE(items
), CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
194 (LPBYTE
)&header
->pbData
, &header
->cbData
);
197 /* Trick: subtract the content length from the reported length,
198 * as the actual content hasn't come yet.
200 header
->cbData
-= msg
->base
.stream_info
.cbContent
;
206 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
207 DWORD cbData
, BOOL fFinal
)
209 CDataEncodeMsg
*msg
= hCryptMsg
;
212 if (msg
->base
.state
== MsgStateFinalized
)
213 SetLastError(CRYPT_E_MSG_ERROR
);
214 else if (msg
->base
.streamed
)
218 if (msg
->base
.state
!= MsgStateUpdated
)
220 CRYPT_DATA_BLOB header
;
222 ret
= CRYPT_EncodeDataContentInfoHeader(msg
, &header
);
225 ret
= msg
->base
.stream_info
.pfnStreamOutput(
226 msg
->base
.stream_info
.pvArg
, header
.pbData
, header
.cbData
,
228 LocalFree(header
.pbData
);
231 /* Curiously, every indefinite-length streamed update appears to
232 * get its own tag and length, regardless of fFinal.
234 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
239 ret
= CRYPT_EncodeContentLength(X509_ASN_ENCODING
, NULL
,
240 &cbData
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (BYTE
*)&header
,
244 ret
= msg
->base
.stream_info
.pfnStreamOutput(
245 msg
->base
.stream_info
.pvArg
, header
, headerLen
,
252 ret
= msg
->base
.stream_info
.pfnStreamOutput(
253 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
255 msg
->base
.state
= MsgStateUpdated
;
259 msg
->base
.state
= MsgStateFinalized
;
260 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
262 BYTE indefinite_trailer
[6] = { 0 };
264 ret
= msg
->base
.stream_info
.pfnStreamOutput(
265 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
268 ret
= msg
->base
.stream_info
.pfnStreamOutput(
269 msg
->base
.stream_info
.pvArg
, indefinite_trailer
,
270 sizeof(indefinite_trailer
), TRUE
);
273 ret
= msg
->base
.stream_info
.pfnStreamOutput(
274 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
, TRUE
);
279 SetLastError(STATUS_ACCESS_VIOLATION
);
288 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
289 SetLastError(E_INVALIDARG
);
291 SetLastError(CRYPT_E_MSG_ERROR
);
295 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
297 msg
->base
.state
= MsgStateFinalized
;
298 /* non-streamed data messages don't allow non-final updates,
299 * don't bother checking whether data already exist, they can't.
301 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
302 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
303 &msg
->bare_content_len
);
309 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
316 else if (*pcbData
< len
)
319 SetLastError(ERROR_MORE_DATA
);
325 memcpy(pvData
, src
, len
);
330 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
331 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
333 CDataEncodeMsg
*msg
= hCryptMsg
;
338 case CMSG_CONTENT_PARAM
:
339 if (msg
->base
.streamed
)
340 SetLastError(E_INVALIDARG
);
343 CRYPT_CONTENT_INFO info
;
344 char rsa_data
[] = "1.2.840.113549.1.7.1";
346 info
.pszObjId
= rsa_data
;
347 info
.Content
.cbData
= msg
->bare_content_len
;
348 info
.Content
.pbData
= msg
->bare_content
;
349 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
353 case CMSG_BARE_CONTENT_PARAM
:
354 if (msg
->base
.streamed
)
355 SetLastError(E_INVALIDARG
);
357 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->bare_content
,
358 msg
->bare_content_len
);
361 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
366 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
367 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
373 SetLastError(E_INVALIDARG
);
376 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
379 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
380 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
,
381 CRYPT_DefaultMsgControl
);
382 msg
->bare_content_len
= sizeof(empty_data_content
);
383 msg
->bare_content
= (LPBYTE
)empty_data_content
;
388 typedef struct _CHashEncodeMsg
393 CRYPT_DATA_BLOB data
;
396 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
398 CHashEncodeMsg
*msg
= hCryptMsg
;
400 CryptMemFree(msg
->data
.pbData
);
401 CryptDestroyHash(msg
->hash
);
402 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
403 CryptReleaseContext(msg
->prov
, 0);
406 static BOOL
CRYPT_EncodePKCSDigestedData(CHashEncodeMsg
*msg
, void *pvData
,
411 DWORD size
= sizeof(algID
);
413 ret
= CryptGetHashParam(msg
->hash
, HP_ALGID
, (BYTE
*)&algID
, &size
, 0);
416 CRYPT_DIGESTED_DATA digestedData
= { 0 };
417 char oid_rsa_data
[] = szOID_RSA_data
;
419 digestedData
.version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
420 digestedData
.DigestAlgorithm
.pszObjId
= (LPSTR
)CertAlgIdToOID(algID
);
421 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
422 /* Quirk: OID is only encoded messages if an update has happened */
423 if (msg
->base
.state
!= MsgStateInit
)
424 digestedData
.ContentInfo
.pszObjId
= oid_rsa_data
;
425 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->data
.cbData
)
427 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &msg
->data
,
428 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
429 (LPBYTE
)&digestedData
.ContentInfo
.Content
.pbData
,
430 &digestedData
.ContentInfo
.Content
.cbData
);
432 if (msg
->base
.state
== MsgStateFinalized
)
433 ret
= extract_hash(msg
->hash
, &digestedData
.hash
.pbData
, &digestedData
.hash
.cbData
);
435 ret
= CRYPT_AsnEncodePKCSDigestedData(&digestedData
, pvData
,
437 CryptMemFree(digestedData
.hash
.pbData
);
438 LocalFree(digestedData
.ContentInfo
.Content
.pbData
);
443 static BOOL
CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
444 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
446 CHashEncodeMsg
*msg
= hCryptMsg
;
449 TRACE("(%p, %ld, %ld, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
454 case CMSG_BARE_CONTENT_PARAM
:
455 if (msg
->base
.streamed
)
456 SetLastError(E_INVALIDARG
);
458 ret
= CRYPT_EncodePKCSDigestedData(msg
, pvData
, pcbData
);
460 case CMSG_CONTENT_PARAM
:
462 CRYPT_CONTENT_INFO info
;
464 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
465 &info
.Content
.cbData
);
468 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
469 if (info
.Content
.pbData
)
471 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
472 info
.Content
.pbData
, &info
.Content
.cbData
);
475 char oid_rsa_hashed
[] = szOID_RSA_hashedData
;
477 info
.pszObjId
= oid_rsa_hashed
;
478 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
479 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
481 CryptMemFree(info
.Content
.pbData
);
488 case CMSG_COMPUTED_HASH_PARAM
:
489 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
491 case CMSG_VERSION_PARAM
:
492 if (msg
->base
.state
!= MsgStateFinalized
)
493 SetLastError(CRYPT_E_MSG_ERROR
);
496 DWORD version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
498 /* Since the data are always encoded as octets, the version is
499 * always 0 (see rfc3852, section 7)
501 ret
= CRYPT_CopyParam(pvData
, pcbData
, &version
, sizeof(version
));
505 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
510 static BOOL
CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
511 DWORD cbData
, BOOL fFinal
)
513 CHashEncodeMsg
*msg
= hCryptMsg
;
516 TRACE("(%p, %p, %ld, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
518 if (msg
->base
.state
== MsgStateFinalized
)
519 SetLastError(CRYPT_E_MSG_ERROR
);
520 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
522 /* Doesn't do much, as stream output is never called, and you
523 * can't get the content.
525 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
526 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
531 SetLastError(CRYPT_E_MSG_ERROR
);
534 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
537 msg
->data
.pbData
= CryptMemAlloc(cbData
);
538 if (msg
->data
.pbData
)
540 memcpy(msg
->data
.pbData
+ msg
->data
.cbData
, pbData
, cbData
);
541 msg
->data
.cbData
+= cbData
;
546 msg
->base
.state
= MsgStateFinalized
;
552 static HCRYPTMSG
CHashEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
553 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
556 const CMSG_HASHED_ENCODE_INFO
*info
= pvMsgEncodeInfo
;
560 if (info
->cbSize
!= sizeof(CMSG_HASHED_ENCODE_INFO
))
562 SetLastError(E_INVALIDARG
);
565 if (!(algID
= CertOIDToAlgId(info
->HashAlgorithm
.pszObjId
)))
567 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
570 if (info
->hCryptProv
)
571 prov
= info
->hCryptProv
;
574 prov
= I_CryptGetDefaultCryptProv(algID
);
577 SetLastError(E_INVALIDARG
);
580 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
582 msg
= CryptMemAlloc(sizeof(CHashEncodeMsg
));
585 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
586 CHashEncodeMsg_Close
, CHashEncodeMsg_GetParam
, CHashEncodeMsg_Update
,
587 CRYPT_DefaultMsgControl
);
589 msg
->data
.cbData
= 0;
590 msg
->data
.pbData
= NULL
;
591 if (!CryptCreateHash(prov
, algID
, 0, 0, &msg
->hash
))
600 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
603 PCERT_INFO pCertInfo
;
604 HCRYPTPROV hCryptProv
;
606 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm
;
609 PCRYPT_ATTRIBUTE rgAuthAttr
;
611 PCRYPT_ATTRIBUTE rgUnauthAttr
;
613 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm
;
614 void *pvHashEncryptionAuxInfo
;
615 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS
;
617 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
621 CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*rgSigners
;
623 PCERT_BLOB rgCertEncoded
;
625 PCRL_BLOB rgCrlEncoded
;
626 DWORD cAttrCertEncoded
;
627 PCERT_BLOB rgAttrCertEncoded
;
628 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS
;
630 static BOOL
CRYPT_IsValidSigner(const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*signer
)
632 if (signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO
) &&
633 signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
635 SetLastError(E_INVALIDARG
);
638 if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
640 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
642 SetLastError(E_INVALIDARG
);
645 if (!signer
->pCertInfo
->Issuer
.cbData
)
647 SetLastError(E_INVALIDARG
);
651 else if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
653 switch (signer
->SignerId
.dwIdChoice
)
656 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
658 SetLastError(E_INVALIDARG
);
661 if (!signer
->pCertInfo
->Issuer
.cbData
)
663 SetLastError(E_INVALIDARG
);
667 case CERT_ID_ISSUER_SERIAL_NUMBER
:
668 if (!signer
->SignerId
.IssuerSerialNumber
.SerialNumber
.cbData
)
670 SetLastError(E_INVALIDARG
);
673 if (!signer
->SignerId
.IssuerSerialNumber
.Issuer
.cbData
)
675 SetLastError(E_INVALIDARG
);
679 case CERT_ID_KEY_IDENTIFIER
:
680 if (!signer
->SignerId
.KeyId
.cbData
)
682 SetLastError(E_INVALIDARG
);
687 SetLastError(E_INVALIDARG
);
689 if (signer
->HashEncryptionAlgorithm
.pszObjId
)
691 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
695 if (!signer
->hCryptProv
)
697 SetLastError(E_INVALIDARG
);
700 if (!CertOIDToAlgId(signer
->HashAlgorithm
.pszObjId
))
702 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
708 static BOOL
CRYPT_ConstructBlob(CRYPT_DATA_BLOB
*out
, const CRYPT_DATA_BLOB
*in
)
712 out
->cbData
= in
->cbData
;
715 out
->pbData
= CryptMemAlloc(out
->cbData
);
717 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
726 static BOOL
CRYPT_ConstructBlobArray(DWORD
*outCBlobs
,
727 PCRYPT_DATA_BLOB
*outPBlobs
, DWORD cBlobs
, const CRYPT_DATA_BLOB
*pBlobs
)
734 *outPBlobs
= CryptMemAlloc(cBlobs
* sizeof(CRYPT_DATA_BLOB
));
739 memset(*outPBlobs
, 0, cBlobs
* sizeof(CRYPT_DATA_BLOB
));
740 for (i
= 0; ret
&& i
< cBlobs
; i
++)
741 ret
= CRYPT_ConstructBlob(&(*outPBlobs
)[i
], &pBlobs
[i
]);
749 static void CRYPT_FreeBlobArray(DWORD cBlobs
, PCRYPT_DATA_BLOB blobs
)
753 for (i
= 0; i
< cBlobs
; i
++)
754 CryptMemFree(blobs
[i
].pbData
);
758 static BOOL
CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE
*out
,
759 const CRYPT_ATTRIBUTE
*in
)
763 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
766 strcpy(out
->pszObjId
, in
->pszObjId
);
767 ret
= CRYPT_ConstructBlobArray(&out
->cValue
, &out
->rgValue
,
768 in
->cValue
, in
->rgValue
);
775 static BOOL
CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES
*out
,
776 const CRYPT_ATTRIBUTES
*in
)
780 out
->cAttr
= in
->cAttr
;
783 out
->rgAttr
= CryptMemAlloc(out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
788 memset(out
->rgAttr
, 0, out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
789 for (i
= 0; ret
&& i
< out
->cAttr
; i
++)
790 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[i
], &in
->rgAttr
[i
]);
800 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
801 static BOOL
CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO
*info
,
802 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*in
)
806 if (in
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
808 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
809 ret
= CRYPT_ConstructBlob(&info
->SignerId
.IssuerSerialNumber
.Issuer
,
810 &in
->pCertInfo
->Issuer
);
812 ret
= CRYPT_ConstructBlob(
813 &info
->SignerId
.IssuerSerialNumber
.SerialNumber
,
814 &in
->pCertInfo
->SerialNumber
);
815 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
816 info
->HashEncryptionAlgorithm
.pszObjId
=
817 in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
;
819 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
820 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.Parameters
);
824 const CRYPT_ALGORITHM_IDENTIFIER
*pEncrAlg
;
826 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS).
827 * See CRYPT_IsValidSigner.
829 if (!in
->SignerId
.dwIdChoice
)
831 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
832 ret
= CRYPT_ConstructBlob(&info
->SignerId
.IssuerSerialNumber
.Issuer
,
833 &in
->pCertInfo
->Issuer
);
835 ret
= CRYPT_ConstructBlob(
836 &info
->SignerId
.IssuerSerialNumber
.SerialNumber
,
837 &in
->pCertInfo
->SerialNumber
);
838 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
840 else if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
842 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
843 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
844 ret
= CRYPT_ConstructBlob(&info
->SignerId
.IssuerSerialNumber
.Issuer
,
845 &in
->SignerId
.IssuerSerialNumber
.Issuer
);
847 ret
= CRYPT_ConstructBlob(
848 &info
->SignerId
.IssuerSerialNumber
.SerialNumber
,
849 &in
->SignerId
.IssuerSerialNumber
.SerialNumber
);
853 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */
854 info
->dwVersion
= CMSG_SIGNER_INFO_V3
;
855 info
->SignerId
.dwIdChoice
= CERT_ID_KEY_IDENTIFIER
;
856 ret
= CRYPT_ConstructBlob(&info
->SignerId
.KeyId
,
857 &in
->SignerId
.KeyId
);
859 pEncrAlg
= in
->HashEncryptionAlgorithm
.pszObjId
?
860 &in
->HashEncryptionAlgorithm
:
861 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
;
862 info
->HashEncryptionAlgorithm
.pszObjId
= pEncrAlg
->pszObjId
;
864 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
865 &pEncrAlg
->Parameters
);
867 /* Assumption: algorithm IDs will point to static strings, not
868 * stack-based ones, so copying the pointer values is safe.
870 info
->HashAlgorithm
.pszObjId
= in
->HashAlgorithm
.pszObjId
;
872 ret
= CRYPT_ConstructBlob(&info
->HashAlgorithm
.Parameters
,
873 &in
->HashAlgorithm
.Parameters
);
875 ret
= CRYPT_ConstructAttributes(&info
->AuthAttrs
,
876 (CRYPT_ATTRIBUTES
*)&in
->cAuthAttr
);
878 ret
= CRYPT_ConstructAttributes(&info
->UnauthAttrs
,
879 (CRYPT_ATTRIBUTES
*)&in
->cUnauthAttr
);
883 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO
*info
)
887 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
889 CryptMemFree(info
->SignerId
.IssuerSerialNumber
.Issuer
.pbData
);
890 CryptMemFree(info
->SignerId
.IssuerSerialNumber
.SerialNumber
.pbData
);
893 CryptMemFree(info
->SignerId
.KeyId
.pbData
);
894 CryptMemFree(info
->HashAlgorithm
.Parameters
.pbData
);
895 CryptMemFree(info
->HashEncryptionAlgorithm
.Parameters
.pbData
);
896 CryptMemFree(info
->EncryptedHash
.pbData
);
897 for (i
= 0; i
< info
->AuthAttrs
.cAttr
; i
++)
899 for (j
= 0; j
< info
->AuthAttrs
.rgAttr
[i
].cValue
; j
++)
900 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
901 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
);
902 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].pszObjId
);
904 CryptMemFree(info
->AuthAttrs
.rgAttr
);
905 for (i
= 0; i
< info
->UnauthAttrs
.cAttr
; i
++)
907 for (j
= 0; j
< info
->UnauthAttrs
.rgAttr
[i
].cValue
; j
++)
908 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
909 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
);
910 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].pszObjId
);
912 CryptMemFree(info
->UnauthAttrs
.rgAttr
);
915 typedef struct _CSignerHandles
917 HCRYPTHASH contentHash
;
918 HCRYPTHASH authAttrHash
;
921 typedef struct _CSignedMsgData
923 CRYPT_SIGNED_INFO
*info
;
925 CSignerHandles
*signerHandles
;
928 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
929 * Assumes signerIndex is a valid index, and that msg_data's info has already
932 static BOOL
CSignedMsgData_ConstructSignerHandles(CSignedMsgData
*msg_data
,
933 DWORD signerIndex
, HCRYPTPROV
*crypt_prov
, DWORD
*flags
)
938 algID
= CertOIDToAlgId(
939 msg_data
->info
->rgSignerInfo
[signerIndex
].HashAlgorithm
.pszObjId
);
943 *crypt_prov
= I_CryptGetDefaultCryptProv(algID
);
944 if (!*crypt_prov
) return FALSE
;
945 *flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
948 ret
= CryptCreateHash(*crypt_prov
, algID
, 0, 0,
949 &msg_data
->signerHandles
->contentHash
);
950 if (ret
&& msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
> 0)
951 ret
= CryptCreateHash(*crypt_prov
, algID
, 0, 0,
952 &msg_data
->signerHandles
->authAttrHash
);
956 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
959 static BOOL
CSignedMsgData_AllocateHandles(CSignedMsgData
*msg_data
)
963 if (msg_data
->info
->cSignerInfo
)
965 msg_data
->signerHandles
=
966 CryptMemAlloc(msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
967 if (msg_data
->signerHandles
)
969 msg_data
->cSignerHandle
= msg_data
->info
->cSignerInfo
;
970 memset(msg_data
->signerHandles
, 0,
971 msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
975 msg_data
->cSignerHandle
= 0;
981 msg_data
->cSignerHandle
= 0;
982 msg_data
->signerHandles
= NULL
;
987 static void CSignedMsgData_CloseHandles(CSignedMsgData
*msg_data
)
991 for (i
= 0; i
< msg_data
->cSignerHandle
; i
++)
993 if (msg_data
->signerHandles
[i
].contentHash
)
994 CryptDestroyHash(msg_data
->signerHandles
[i
].contentHash
);
995 if (msg_data
->signerHandles
[i
].authAttrHash
)
996 CryptDestroyHash(msg_data
->signerHandles
[i
].authAttrHash
);
998 CryptMemFree(msg_data
->signerHandles
);
999 msg_data
->signerHandles
= NULL
;
1000 msg_data
->cSignerHandle
= 0;
1003 static BOOL
CSignedMsgData_UpdateHash(CSignedMsgData
*msg_data
,
1004 const BYTE
*pbData
, DWORD cbData
)
1009 for (i
= 0; ret
&& i
< msg_data
->cSignerHandle
; i
++)
1010 ret
= CryptHashData(msg_data
->signerHandles
[i
].contentHash
, pbData
,
1015 static BOOL
CRYPT_AppendAttribute(CRYPT_ATTRIBUTES
*out
,
1016 const CRYPT_ATTRIBUTE
*in
)
1020 out
->rgAttr
= CryptMemRealloc(out
->rgAttr
,
1021 (out
->cAttr
+ 1) * sizeof(CRYPT_ATTRIBUTE
));
1024 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[out
->cAttr
], in
);
1031 static BOOL
CSignedMsgData_AppendMessageDigestAttribute(
1032 CSignedMsgData
*msg_data
, DWORD signerIndex
)
1035 CRYPT_HASH_BLOB hash
= { 0, NULL
}, encodedHash
= { 0, NULL
};
1036 char messageDigest
[] = szOID_RSA_messageDigest
;
1037 CRYPT_ATTRIBUTE messageDigestAttr
= { messageDigest
, 1, &encodedHash
};
1039 if (!(ret
= extract_hash(msg_data
->signerHandles
[signerIndex
].contentHash
, &hash
.pbData
, &hash
.cbData
)))
1042 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &hash
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (LPBYTE
)&encodedHash
.pbData
,
1043 &encodedHash
.cbData
);
1046 ret
= CRYPT_AppendAttribute(
1047 &msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
,
1048 &messageDigestAttr
);
1049 LocalFree(encodedHash
.pbData
);
1051 CryptMemFree(hash
.pbData
);
1060 static BOOL
CSignedMsgData_UpdateAuthenticatedAttributes(
1061 CSignedMsgData
*msg_data
, SignOrVerify flag
)
1066 TRACE("(%p)\n", msg_data
);
1068 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1070 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1074 BYTE oid_rsa_data_encoded
[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
1075 0xf7,0x0d,0x01,0x07,0x01 };
1076 CRYPT_DATA_BLOB content
= { sizeof(oid_rsa_data_encoded
),
1077 oid_rsa_data_encoded
};
1078 char contentType
[] = szOID_RSA_contentType
;
1079 CRYPT_ATTRIBUTE contentTypeAttr
= { contentType
, 1, &content
};
1081 /* FIXME: does this depend on inner OID? */
1082 ret
= CRYPT_AppendAttribute(
1083 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
, &contentTypeAttr
);
1085 ret
= CSignedMsgData_AppendMessageDigestAttribute(msg_data
,
1090 LPBYTE encodedAttrs
;
1093 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, PKCS_ATTRIBUTES
,
1094 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
,
1095 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &encodedAttrs
, &size
);
1098 ret
= CryptHashData(
1099 msg_data
->signerHandles
[i
].authAttrHash
, encodedAttrs
,
1101 LocalFree(encodedAttrs
);
1106 TRACE("returning %d\n", ret
);
1110 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB
*hash
)
1115 for (i
= 0; i
< hash
->cbData
/ 2; i
++)
1117 tmp
= hash
->pbData
[hash
->cbData
- i
- 1];
1118 hash
->pbData
[hash
->cbData
- i
- 1] = hash
->pbData
[i
];
1119 hash
->pbData
[i
] = tmp
;
1123 static BOOL
CSignedMsgData_Sign(CSignedMsgData
*msg_data
)
1128 TRACE("(%p)\n", msg_data
);
1130 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1133 DWORD keySpec
= msg_data
->info
->signerKeySpec
[i
];
1136 keySpec
= AT_SIGNATURE
;
1137 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1138 hash
= msg_data
->signerHandles
[i
].authAttrHash
;
1140 hash
= msg_data
->signerHandles
[i
].contentHash
;
1141 ret
= CryptSignHashW(hash
, keySpec
, NULL
, 0, NULL
,
1142 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1145 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
=
1147 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1148 if (msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
)
1150 ret
= CryptSignHashW(hash
, keySpec
, NULL
, 0,
1151 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
,
1152 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1155 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
);
1164 static BOOL
CSignedMsgData_Update(CSignedMsgData
*msg_data
,
1165 const BYTE
*pbData
, DWORD cbData
, BOOL fFinal
, SignOrVerify flag
)
1167 BOOL ret
= CSignedMsgData_UpdateHash(msg_data
, pbData
, cbData
);
1171 ret
= CSignedMsgData_UpdateAuthenticatedAttributes(msg_data
, flag
);
1172 if (ret
&& flag
== Sign
)
1173 ret
= CSignedMsgData_Sign(msg_data
);
1178 typedef struct _CSignedEncodeMsg
1182 CRYPT_DATA_BLOB data
;
1183 CSignedMsgData msg_data
;
1186 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1188 CSignedEncodeMsg
*msg
= hCryptMsg
;
1191 CryptMemFree(msg
->innerOID
);
1192 CryptMemFree(msg
->data
.pbData
);
1193 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCertEncoded
,
1194 msg
->msg_data
.info
->rgCertEncoded
);
1195 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCrlEncoded
,
1196 msg
->msg_data
.info
->rgCrlEncoded
);
1197 for (i
= 0; i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1198 CSignerInfo_Free(&msg
->msg_data
.info
->rgSignerInfo
[i
]);
1199 CSignedMsgData_CloseHandles(&msg
->msg_data
);
1200 CryptMemFree(msg
->msg_data
.info
->signerKeySpec
);
1201 CryptMemFree(msg
->msg_data
.info
->rgSignerInfo
);
1202 CryptMemFree(msg
->msg_data
.info
);
1205 static BOOL
CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1206 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1208 CSignedEncodeMsg
*msg
= hCryptMsg
;
1211 switch (dwParamType
)
1213 case CMSG_CONTENT_PARAM
:
1215 CRYPT_CONTENT_INFO info
;
1217 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1218 &info
.Content
.cbData
);
1221 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1222 if (info
.Content
.pbData
)
1224 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1225 info
.Content
.pbData
, &info
.Content
.cbData
);
1228 char oid_rsa_signed
[] = szOID_RSA_signedData
;
1230 info
.pszObjId
= oid_rsa_signed
;
1231 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1232 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1234 CryptMemFree(info
.Content
.pbData
);
1241 case CMSG_BARE_CONTENT_PARAM
:
1243 CRYPT_SIGNED_INFO info
;
1244 BOOL freeContent
= FALSE
;
1246 info
= *msg
->msg_data
.info
;
1247 if (!msg
->innerOID
|| !strcmp(msg
->innerOID
, szOID_RSA_data
))
1249 char oid_rsa_data
[] = szOID_RSA_data
;
1251 /* Quirk: OID is only encoded messages if an update has happened */
1252 if (msg
->base
.state
!= MsgStateInit
)
1253 info
.content
.pszObjId
= oid_rsa_data
;
1255 info
.content
.pszObjId
= NULL
;
1256 if (msg
->data
.cbData
)
1258 CRYPT_DATA_BLOB blob
= { msg
->data
.cbData
, msg
->data
.pbData
};
1260 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1261 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
1262 &info
.content
.Content
.pbData
, &info
.content
.Content
.cbData
);
1267 info
.content
.Content
.cbData
= 0;
1268 info
.content
.Content
.pbData
= NULL
;
1274 info
.content
.pszObjId
= msg
->innerOID
;
1275 info
.content
.Content
.cbData
= msg
->data
.cbData
;
1276 info
.content
.Content
.pbData
= msg
->data
.pbData
;
1281 ret
= CRYPT_AsnEncodeCMSSignedInfo(&info
, pvData
, pcbData
);
1283 LocalFree(info
.content
.Content
.pbData
);
1287 case CMSG_COMPUTED_HASH_PARAM
:
1288 if (dwIndex
>= msg
->msg_data
.cSignerHandle
)
1289 SetLastError(CRYPT_E_INVALID_INDEX
);
1291 ret
= CryptGetHashParam(
1292 msg
->msg_data
.signerHandles
[dwIndex
].contentHash
, HP_HASHVAL
,
1293 pvData
, pcbData
, 0);
1295 case CMSG_ENCODED_SIGNER
:
1296 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1297 SetLastError(CRYPT_E_INVALID_INDEX
);
1299 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1300 CMS_SIGNER_INFO
, &msg
->msg_data
.info
->rgSignerInfo
[dwIndex
], 0,
1301 NULL
, pvData
, pcbData
);
1303 case CMSG_VERSION_PARAM
:
1304 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->msg_data
.info
->version
,
1305 sizeof(msg
->msg_data
.info
->version
));
1308 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1313 static BOOL
CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1314 DWORD cbData
, BOOL fFinal
)
1316 CSignedEncodeMsg
*msg
= hCryptMsg
;
1319 if (msg
->base
.state
== MsgStateFinalized
)
1320 SetLastError(CRYPT_E_MSG_ERROR
);
1321 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1323 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
, fFinal
,
1325 if (msg
->base
.streamed
)
1326 FIXME("streamed partial stub\n");
1327 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1332 SetLastError(CRYPT_E_MSG_ERROR
);
1337 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1338 if (msg
->data
.pbData
)
1340 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1341 msg
->data
.cbData
= cbData
;
1348 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
,
1350 msg
->base
.state
= MsgStateFinalized
;
1356 static HCRYPTMSG
CSignedEncodeMsg_Open(DWORD dwFlags
,
1357 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1358 PCMSG_STREAM_INFO pStreamInfo
)
1360 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1362 CSignedEncodeMsg
*msg
;
1364 if (info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO
) &&
1365 info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1367 SetLastError(E_INVALIDARG
);
1370 if (info
->cbSize
== sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
) &&
1371 info
->cAttrCertEncoded
)
1373 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1376 for (i
= 0; i
< info
->cSigners
; i
++)
1377 if (!CRYPT_IsValidSigner(&info
->rgSigners
[i
]))
1379 msg
= CryptMemAlloc(sizeof(CSignedEncodeMsg
));
1384 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1385 CSignedEncodeMsg_Close
, CSignedEncodeMsg_GetParam
,
1386 CSignedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1387 if (pszInnerContentObjID
)
1389 msg
->innerOID
= CryptMemAlloc(strlen(pszInnerContentObjID
) + 1);
1391 strcpy(msg
->innerOID
, pszInnerContentObjID
);
1396 msg
->innerOID
= NULL
;
1397 msg
->data
.cbData
= 0;
1398 msg
->data
.pbData
= NULL
;
1400 msg
->msg_data
.info
= CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO
));
1402 msg
->msg_data
.info
= NULL
;
1403 if (msg
->msg_data
.info
)
1405 memset(msg
->msg_data
.info
, 0, sizeof(CRYPT_SIGNED_INFO
));
1406 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V1
;
1414 msg
->msg_data
.info
->rgSignerInfo
=
1415 CryptMemAlloc(info
->cSigners
* sizeof(CMSG_CMS_SIGNER_INFO
));
1416 if (msg
->msg_data
.info
->rgSignerInfo
)
1418 msg
->msg_data
.info
->cSignerInfo
= info
->cSigners
;
1419 memset(msg
->msg_data
.info
->rgSignerInfo
, 0,
1420 msg
->msg_data
.info
->cSignerInfo
*
1421 sizeof(CMSG_CMS_SIGNER_INFO
));
1422 ret
= CSignedMsgData_AllocateHandles(&msg
->msg_data
);
1423 msg
->msg_data
.info
->signerKeySpec
= CryptMemAlloc(info
->cSigners
* sizeof(DWORD
));
1424 if (!msg
->msg_data
.info
->signerKeySpec
)
1426 for (i
= 0; ret
&& i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1428 if (info
->rgSigners
[i
].SignerId
.dwIdChoice
==
1429 CERT_ID_KEY_IDENTIFIER
)
1430 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V3
;
1431 ret
= CSignerInfo_Construct(
1432 &msg
->msg_data
.info
->rgSignerInfo
[i
],
1433 &info
->rgSigners
[i
]);
1436 ret
= CSignedMsgData_ConstructSignerHandles(
1437 &msg
->msg_data
, i
, &info
->rgSigners
[i
].hCryptProv
, &dwFlags
);
1438 if (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1439 CryptReleaseContext(info
->rgSigners
[i
].hCryptProv
,
1442 msg
->msg_data
.info
->signerKeySpec
[i
] =
1443 info
->rgSigners
[i
].dwKeySpec
;
1451 msg
->msg_data
.info
->cSignerInfo
= 0;
1452 msg
->msg_data
.signerHandles
= NULL
;
1453 msg
->msg_data
.cSignerHandle
= 0;
1457 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCertEncoded
,
1458 &msg
->msg_data
.info
->rgCertEncoded
, info
->cCertEncoded
,
1459 info
->rgCertEncoded
);
1461 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCrlEncoded
,
1462 &msg
->msg_data
.info
->rgCrlEncoded
, info
->cCrlEncoded
,
1463 info
->rgCrlEncoded
);
1466 CSignedEncodeMsg_Close(msg
);
1474 typedef struct _CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
1477 HCRYPTPROV_LEGACY hCryptProv
;
1478 CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm
;
1479 void *pvEncryptionAuxInfo
;
1481 PCERT_INFO
*rgpRecipientCert
;
1482 PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients
;
1484 PCERT_BLOB rgCertEncoded
;
1486 PCRL_BLOB rgCrlEncoded
;
1487 DWORD cAttrCertEncoded
;
1488 PCERT_BLOB rgAttrCertEncoded
;
1489 DWORD cUnprotectedAttr
;
1490 PCRYPT_ATTRIBUTE rgUnprotectedAttr
;
1491 } CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
;
1493 typedef struct _CEnvelopedEncodeMsg
1496 CRYPT_ALGORITHM_IDENTIFIER algo
;
1499 DWORD cRecipientInfo
;
1500 CMSG_KEY_TRANS_RECIPIENT_INFO
*recipientInfo
;
1501 CRYPT_DATA_BLOB data
;
1502 } CEnvelopedEncodeMsg
;
1504 static BOOL
CRYPT_ConstructAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
1505 const CRYPT_ALGORITHM_IDENTIFIER
*in
)
1507 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
1510 strcpy(out
->pszObjId
, in
->pszObjId
);
1511 return CRYPT_ConstructBlob(&out
->Parameters
, &in
->Parameters
);
1517 static BOOL
CRYPT_ConstructBitBlob(CRYPT_BIT_BLOB
*out
, const CRYPT_BIT_BLOB
*in
)
1519 out
->cbData
= in
->cbData
;
1520 out
->cUnusedBits
= in
->cUnusedBits
;
1523 out
->pbData
= CryptMemAlloc(out
->cbData
);
1525 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
1534 static BOOL
CRYPT_GenKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, ALG_ID algID
)
1536 static HCRYPTOIDFUNCSET set
= NULL
;
1537 PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY genKeyFunc
= NULL
;
1538 HCRYPTOIDFUNCADDR hFunc
;
1542 set
= CryptInitOIDFunctionSet(CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC
, 0);
1543 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1544 info
->ContentEncryptionAlgorithm
.pszObjId
, 0, (void **)&genKeyFunc
, &hFunc
);
1547 ret
= genKeyFunc(info
, 0, NULL
);
1548 CryptFreeOIDFunctionAddress(hFunc
, 0);
1551 ret
= CryptGenKey(info
->hCryptProv
, algID
, CRYPT_EXPORTABLE
,
1552 &info
->hContentEncryptKey
);
1556 static BOOL WINAPI
CRYPT_ExportKeyTrans(
1557 PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo
,
1558 PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo
,
1559 PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo
,
1560 DWORD dwFlags
, void *pvReserved
)
1562 CERT_PUBLIC_KEY_INFO keyInfo
;
1566 ret
= CRYPT_ConstructAlgorithmId(&keyInfo
.Algorithm
,
1567 &pKeyTransEncodeInfo
->KeyEncryptionAlgorithm
);
1569 ret
= CRYPT_ConstructBitBlob(&keyInfo
.PublicKey
,
1570 &pKeyTransEncodeInfo
->RecipientPublicKey
);
1572 ret
= CryptImportPublicKeyInfo(pKeyTransEncodeInfo
->hCryptProv
,
1573 X509_ASN_ENCODING
, &keyInfo
, &expKey
);
1578 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
, expKey
,
1579 SIMPLEBLOB
, 0, NULL
, &size
);
1584 keyBlob
= CryptMemAlloc(size
);
1587 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
,
1588 expKey
, SIMPLEBLOB
, 0, keyBlob
, &size
);
1591 DWORD head
= sizeof(BLOBHEADER
) + sizeof(ALG_ID
);
1593 pKeyTransEncryptInfo
->EncryptedKey
.pbData
=
1594 CryptMemAlloc(size
- head
);
1595 if (pKeyTransEncryptInfo
->EncryptedKey
.pbData
)
1599 pKeyTransEncryptInfo
->EncryptedKey
.cbData
= size
- head
;
1600 for (i
= size
- 1; i
>= head
; --i
, ++k
)
1601 pKeyTransEncryptInfo
->EncryptedKey
.pbData
[k
] =
1607 CryptMemFree(keyBlob
);
1612 CryptDestroyKey(expKey
);
1615 CryptMemFree(keyInfo
.PublicKey
.pbData
);
1616 CryptMemFree(keyInfo
.Algorithm
.pszObjId
);
1617 CryptMemFree(keyInfo
.Algorithm
.Parameters
.pbData
);
1621 static BOOL
CRYPT_ExportEncryptedKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, DWORD i
,
1622 CRYPT_DATA_BLOB
*key
)
1624 static HCRYPTOIDFUNCSET set
= NULL
;
1625 PFN_CMSG_EXPORT_KEY_TRANS exportKeyFunc
= NULL
;
1626 HCRYPTOIDFUNCADDR hFunc
= NULL
;
1627 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1628 info
->rgCmsRecipients
[i
].pKeyTrans
;
1629 CMSG_KEY_TRANS_ENCRYPT_INFO encryptInfo
;
1632 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
1633 encryptInfo
.cbSize
= sizeof(encryptInfo
);
1634 encryptInfo
.dwRecipientIndex
= i
;
1635 ret
= CRYPT_ConstructAlgorithmId(&encryptInfo
.KeyEncryptionAlgorithm
,
1636 &encodeInfo
->KeyEncryptionAlgorithm
);
1639 set
= CryptInitOIDFunctionSet(CMSG_OID_EXPORT_KEY_TRANS_FUNC
, 0);
1640 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1641 encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
, 0, (void **)&exportKeyFunc
,
1644 exportKeyFunc
= CRYPT_ExportKeyTrans
;
1647 ret
= exportKeyFunc(info
, encodeInfo
, &encryptInfo
, 0, NULL
);
1650 key
->cbData
= encryptInfo
.EncryptedKey
.cbData
;
1651 key
->pbData
= encryptInfo
.EncryptedKey
.pbData
;
1655 CryptFreeOIDFunctionAddress(hFunc
, 0);
1657 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
);
1658 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.Parameters
.pbData
);
1662 static LPVOID WINAPI
mem_alloc(size_t size
)
1664 return CryptMemAlloc(size
);
1667 static VOID WINAPI
mem_free(LPVOID pv
)
1673 static BOOL
CContentEncryptInfo_Construct(CMSG_CONTENT_ENCRYPT_INFO
*info
,
1674 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*in
, HCRYPTPROV prov
)
1678 info
->cbSize
= sizeof(CMSG_CONTENT_ENCRYPT_INFO
);
1679 info
->hCryptProv
= prov
;
1680 ret
= CRYPT_ConstructAlgorithmId(&info
->ContentEncryptionAlgorithm
,
1681 &in
->ContentEncryptionAlgorithm
);
1682 info
->pvEncryptionAuxInfo
= in
->pvEncryptionAuxInfo
;
1683 info
->cRecipients
= in
->cRecipients
;
1686 info
->rgCmsRecipients
= CryptMemAlloc(in
->cRecipients
*
1687 sizeof(CMSG_RECIPIENT_ENCODE_INFO
));
1688 if (info
->rgCmsRecipients
)
1692 for (i
= 0; ret
&& i
< in
->cRecipients
; ++i
)
1694 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
;
1695 CERT_INFO
*cert
= in
->rgpRecipientCert
[i
];
1697 info
->rgCmsRecipients
[i
].dwRecipientChoice
=
1698 CMSG_KEY_TRANS_RECIPIENT
;
1699 encodeInfo
= CryptMemAlloc(sizeof(*encodeInfo
));
1700 info
->rgCmsRecipients
[i
].pKeyTrans
= encodeInfo
;
1703 encodeInfo
->cbSize
= sizeof(*encodeInfo
);
1704 ret
= CRYPT_ConstructAlgorithmId(
1705 &encodeInfo
->KeyEncryptionAlgorithm
,
1706 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1707 encodeInfo
->pvKeyEncryptionAuxInfo
= NULL
;
1708 encodeInfo
->hCryptProv
= prov
;
1710 ret
= CRYPT_ConstructBitBlob(
1711 &encodeInfo
->RecipientPublicKey
,
1712 &cert
->SubjectPublicKeyInfo
.PublicKey
);
1714 ret
= CRYPT_ConstructBlob(
1715 &encodeInfo
->RecipientId
.IssuerSerialNumber
.Issuer
,
1718 ret
= CRYPT_ConstructBlob(
1719 &encodeInfo
->RecipientId
.IssuerSerialNumber
.SerialNumber
,
1720 &cert
->SerialNumber
);
1729 info
->pfnAlloc
= mem_alloc
;
1730 info
->pfnFree
= mem_free
;
1734 static void CContentEncryptInfo_Free(CMSG_CONTENT_ENCRYPT_INFO
*info
)
1736 CryptMemFree(info
->ContentEncryptionAlgorithm
.pszObjId
);
1737 CryptMemFree(info
->ContentEncryptionAlgorithm
.Parameters
.pbData
);
1738 if (info
->rgCmsRecipients
)
1742 for (i
= 0; i
< info
->cRecipients
; ++i
)
1744 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1745 info
->rgCmsRecipients
[i
].pKeyTrans
;
1747 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.pszObjId
);
1748 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1749 CryptMemFree(encodeInfo
->RecipientPublicKey
.pbData
);
1751 encodeInfo
->RecipientId
.IssuerSerialNumber
.Issuer
.pbData
);
1753 encodeInfo
->RecipientId
.IssuerSerialNumber
.SerialNumber
.pbData
);
1754 CryptMemFree(encodeInfo
);
1756 CryptMemFree(info
->rgCmsRecipients
);
1760 static BOOL
CRecipientInfo_Construct(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
,
1761 const CERT_INFO
*cert
, CRYPT_DATA_BLOB
*key
)
1765 info
->dwVersion
= CMSG_KEY_TRANS_PKCS_1_5_VERSION
;
1766 info
->RecipientId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
1767 ret
= CRYPT_ConstructBlob(&info
->RecipientId
.IssuerSerialNumber
.Issuer
,
1770 ret
= CRYPT_ConstructBlob(
1771 &info
->RecipientId
.IssuerSerialNumber
.SerialNumber
,
1772 &cert
->SerialNumber
);
1774 ret
= CRYPT_ConstructAlgorithmId(&info
->KeyEncryptionAlgorithm
,
1775 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1776 info
->EncryptedKey
.cbData
= key
->cbData
;
1777 info
->EncryptedKey
.pbData
= key
->pbData
;
1781 static void CRecipientInfo_Free(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
)
1783 CryptMemFree(info
->RecipientId
.IssuerSerialNumber
.Issuer
.pbData
);
1784 CryptMemFree(info
->RecipientId
.IssuerSerialNumber
.SerialNumber
.pbData
);
1785 CryptMemFree(info
->KeyEncryptionAlgorithm
.pszObjId
);
1786 CryptMemFree(info
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1787 CryptMemFree(info
->EncryptedKey
.pbData
);
1790 static void CEnvelopedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1792 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1794 CryptMemFree(msg
->algo
.pszObjId
);
1795 CryptMemFree(msg
->algo
.Parameters
.pbData
);
1796 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1797 CryptReleaseContext(msg
->prov
, 0);
1798 CryptDestroyKey(msg
->key
);
1799 if (msg
->recipientInfo
)
1803 for (i
= 0; i
< msg
->cRecipientInfo
; ++i
)
1804 CRecipientInfo_Free(&msg
->recipientInfo
[i
]);
1805 CryptMemFree(msg
->recipientInfo
);
1807 CryptMemFree(msg
->data
.pbData
);
1810 static BOOL
CEnvelopedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1811 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1813 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1816 switch (dwParamType
)
1818 case CMSG_BARE_CONTENT_PARAM
:
1819 if (msg
->base
.streamed
)
1820 SetLastError(E_INVALIDARG
);
1823 char oid_rsa_data
[] = szOID_RSA_data
;
1824 CRYPT_ENVELOPED_DATA envelopedData
= {
1825 CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION
, msg
->cRecipientInfo
,
1826 msg
->recipientInfo
, { oid_rsa_data
, {
1828 { msg
->algo
.Parameters
.cbData
, msg
->algo
.Parameters
.pbData
}
1830 { msg
->data
.cbData
, msg
->data
.pbData
}
1834 ret
= CRYPT_AsnEncodePKCSEnvelopedData(&envelopedData
, pvData
,
1838 case CMSG_CONTENT_PARAM
:
1840 CRYPT_CONTENT_INFO info
;
1842 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1843 &info
.Content
.cbData
);
1846 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1847 if (info
.Content
.pbData
)
1849 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1850 info
.Content
.pbData
, &info
.Content
.cbData
);
1853 char oid_rsa_enveloped
[] = szOID_RSA_envelopedData
;
1855 info
.pszObjId
= oid_rsa_enveloped
;
1856 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1857 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1859 CryptMemFree(info
.Content
.pbData
);
1867 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1872 static BOOL
CEnvelopedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1873 DWORD cbData
, BOOL fFinal
)
1875 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1878 if (msg
->base
.state
== MsgStateFinalized
)
1879 SetLastError(CRYPT_E_MSG_ERROR
);
1880 else if (msg
->base
.streamed
)
1882 FIXME("streamed stub\n");
1883 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1890 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1891 SetLastError(E_INVALIDARG
);
1893 SetLastError(CRYPT_E_MSG_ERROR
);
1899 DWORD dataLen
= cbData
;
1901 msg
->data
.cbData
= cbData
;
1902 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1903 if (msg
->data
.pbData
)
1905 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1906 ret
= CryptEncrypt(msg
->key
, 0, TRUE
, 0, msg
->data
.pbData
,
1907 &dataLen
, msg
->data
.cbData
);
1908 msg
->data
.cbData
= dataLen
;
1909 if (dataLen
> cbData
)
1911 msg
->data
.pbData
= CryptMemRealloc(msg
->data
.pbData
,
1913 if (msg
->data
.pbData
)
1916 ret
= CryptEncrypt(msg
->key
, 0, TRUE
, 0,
1917 msg
->data
.pbData
, &dataLen
, msg
->data
.cbData
);
1923 CryptMemFree(msg
->data
.pbData
);
1929 msg
->data
.cbData
= 0;
1930 msg
->data
.pbData
= NULL
;
1935 msg
->base
.state
= MsgStateFinalized
;
1941 static HCRYPTMSG
CEnvelopedEncodeMsg_Open(DWORD dwFlags
,
1942 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1943 PCMSG_STREAM_INFO pStreamInfo
)
1945 CEnvelopedEncodeMsg
*msg
;
1946 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1950 if (info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO
) &&
1951 info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1953 SetLastError(E_INVALIDARG
);
1956 if (info
->cbSize
== sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1957 FIXME("CMS fields unsupported\n");
1958 if (!(algID
= CertOIDToAlgId(info
->ContentEncryptionAlgorithm
.pszObjId
)))
1960 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
1963 if (info
->cRecipients
&& !info
->rgpRecipientCert
)
1965 SetLastError(E_INVALIDARG
);
1968 if (info
->hCryptProv
)
1969 prov
= info
->hCryptProv
;
1972 prov
= I_CryptGetDefaultCryptProv(0);
1973 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
1975 msg
= CryptMemAlloc(sizeof(CEnvelopedEncodeMsg
));
1978 CRYPT_DATA_BLOB encryptedKey
= { 0, NULL
};
1979 CMSG_CONTENT_ENCRYPT_INFO encryptInfo
;
1983 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1984 CEnvelopedEncodeMsg_Close
, CEnvelopedEncodeMsg_GetParam
,
1985 CEnvelopedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1986 ret
= CRYPT_ConstructAlgorithmId(&msg
->algo
,
1987 &info
->ContentEncryptionAlgorithm
);
1989 msg
->data
.cbData
= 0;
1990 msg
->data
.pbData
= NULL
;
1991 msg
->cRecipientInfo
= info
->cRecipients
;
1992 msg
->recipientInfo
= CryptMemAlloc(info
->cRecipients
*
1993 sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
));
1994 if (!msg
->recipientInfo
)
1996 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
1999 ret
= CContentEncryptInfo_Construct(&encryptInfo
, info
, prov
);
2002 ret
= CRYPT_GenKey(&encryptInfo
, algID
);
2004 msg
->key
= encryptInfo
.hContentEncryptKey
;
2007 for (i
= 0; ret
&& i
< msg
->cRecipientInfo
; ++i
)
2009 ret
= CRYPT_ExportEncryptedKey(&encryptInfo
, i
, &encryptedKey
);
2011 ret
= CRecipientInfo_Construct(&msg
->recipientInfo
[i
],
2012 info
->rgpRecipientCert
[i
], &encryptedKey
);
2014 CContentEncryptInfo_Free(&encryptInfo
);
2021 if (!msg
&& (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
))
2022 CryptReleaseContext(prov
, 0);
2026 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
2027 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
2028 PCMSG_STREAM_INFO pStreamInfo
)
2030 HCRYPTMSG msg
= NULL
;
2032 TRACE("(%08lx, %08lx, %08lx, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
2033 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
2035 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
2037 SetLastError(E_INVALIDARG
);
2043 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2044 pszInnerContentObjID
, pStreamInfo
);
2047 msg
= CHashEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2048 pszInnerContentObjID
, pStreamInfo
);
2051 msg
= CSignedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2052 pszInnerContentObjID
, pStreamInfo
);
2054 case CMSG_ENVELOPED
:
2055 msg
= CEnvelopedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2056 pszInnerContentObjID
, pStreamInfo
);
2058 case CMSG_SIGNED_AND_ENVELOPED
:
2059 case CMSG_ENCRYPTED
:
2060 /* defined but invalid, fall through */
2062 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2067 typedef struct _CEnvelopedDecodeMsg
2069 CRYPT_ENVELOPED_DATA
*data
;
2070 HCRYPTPROV crypt_prov
;
2071 CRYPT_DATA_BLOB content
;
2073 } CEnvelopedDecodeMsg
;
2075 typedef struct _CDecodeMsg
2079 HCRYPTPROV crypt_prov
;
2082 CSignedMsgData signed_data
;
2083 CEnvelopedDecodeMsg enveloped_data
;
2085 CRYPT_DATA_BLOB msg_data
;
2086 CRYPT_DATA_BLOB detached_data
;
2087 CONTEXT_PROPERTY_LIST
*properties
;
2090 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg
)
2092 CDecodeMsg
*msg
= hCryptMsg
;
2094 if (msg
->crypt_prov
&& msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
2095 CryptReleaseContext(msg
->crypt_prov
, 0);
2100 CryptDestroyHash(msg
->u
.hash
);
2102 case CMSG_ENVELOPED
:
2103 if (msg
->u
.enveloped_data
.crypt_prov
)
2104 CryptReleaseContext(msg
->u
.enveloped_data
.crypt_prov
, 0);
2105 LocalFree(msg
->u
.enveloped_data
.data
);
2106 CryptMemFree(msg
->u
.enveloped_data
.content
.pbData
);
2109 if (msg
->u
.signed_data
.info
)
2111 LocalFree(msg
->u
.signed_data
.info
);
2112 CSignedMsgData_CloseHandles(&msg
->u
.signed_data
);
2116 CryptMemFree(msg
->msg_data
.pbData
);
2117 CryptMemFree(msg
->detached_data
.pbData
);
2118 ContextPropertyList_Free(msg
->properties
);
2121 static BOOL
CDecodeMsg_CopyData(CRYPT_DATA_BLOB
*blob
, const BYTE
*pbData
,
2129 blob
->pbData
= CryptMemRealloc(blob
->pbData
,
2130 blob
->cbData
+ cbData
);
2132 blob
->pbData
= CryptMemAlloc(cbData
);
2135 memcpy(blob
->pbData
+ blob
->cbData
, pbData
, cbData
);
2136 blob
->cbData
+= cbData
;
2144 static BOOL
CDecodeMsg_DecodeDataContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
)
2147 CRYPT_DATA_BLOB
*data
;
2150 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
2151 blob
->pbData
, blob
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &data
, &size
);
2154 ret
= ContextPropertyList_SetProperty(msg
->properties
,
2155 CMSG_CONTENT_PARAM
, data
->pbData
, data
->cbData
);
2161 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg
*msg
, DWORD param
,
2162 const CRYPT_ALGORITHM_IDENTIFIER
*id
)
2164 static const BYTE nullParams
[] = { ASN_NULL
, 0 };
2165 CRYPT_ALGORITHM_IDENTIFIER
*copy
;
2166 DWORD len
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
2168 /* Linearize algorithm id */
2169 len
+= strlen(id
->pszObjId
) + 1;
2170 len
+= id
->Parameters
.cbData
;
2171 copy
= CryptMemAlloc(len
);
2175 (LPSTR
)((BYTE
*)copy
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2176 strcpy(copy
->pszObjId
, id
->pszObjId
);
2177 copy
->Parameters
.pbData
= (BYTE
*)copy
->pszObjId
+ strlen(id
->pszObjId
)
2179 /* Trick: omit NULL parameters */
2180 if (id
->Parameters
.cbData
== sizeof(nullParams
) &&
2181 !memcmp(id
->Parameters
.pbData
, nullParams
, sizeof(nullParams
)))
2183 copy
->Parameters
.cbData
= 0;
2184 len
-= sizeof(nullParams
);
2187 copy
->Parameters
.cbData
= id
->Parameters
.cbData
;
2188 if (copy
->Parameters
.cbData
)
2189 memcpy(copy
->Parameters
.pbData
, id
->Parameters
.pbData
,
2190 id
->Parameters
.cbData
);
2191 ContextPropertyList_SetProperty(msg
->properties
, param
, (BYTE
*)copy
,
2197 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER
*id
)
2199 id
->pszObjId
= (LPSTR
)((BYTE
*)id
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2200 id
->Parameters
.pbData
= (BYTE
*)id
->pszObjId
+ strlen(id
->pszObjId
) + 1;
2203 static BOOL
CDecodeMsg_DecodeHashedContent(CDecodeMsg
*msg
,
2204 const CRYPT_DER_BLOB
*blob
)
2207 CRYPT_DIGESTED_DATA
*digestedData
;
2210 ret
= CRYPT_AsnDecodePKCSDigestedData(blob
->pbData
, blob
->cbData
,
2211 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_DIGESTED_DATA
*)&digestedData
,
2215 ContextPropertyList_SetProperty(msg
->properties
, CMSG_VERSION_PARAM
,
2216 (const BYTE
*)&digestedData
->version
, sizeof(digestedData
->version
));
2217 CDecodeMsg_SaveAlgorithmID(msg
, CMSG_HASH_ALGORITHM_PARAM
,
2218 &digestedData
->DigestAlgorithm
);
2219 ContextPropertyList_SetProperty(msg
->properties
,
2220 CMSG_INNER_CONTENT_TYPE_PARAM
,
2221 (const BYTE
*)digestedData
->ContentInfo
.pszObjId
,
2222 digestedData
->ContentInfo
.pszObjId
?
2223 strlen(digestedData
->ContentInfo
.pszObjId
) + 1 : 0);
2224 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
2226 if (digestedData
->ContentInfo
.Content
.cbData
)
2227 CDecodeMsg_DecodeDataContent(msg
,
2228 &digestedData
->ContentInfo
.Content
);
2230 ContextPropertyList_SetProperty(msg
->properties
,
2231 CMSG_CONTENT_PARAM
, NULL
, 0);
2233 ContextPropertyList_SetProperty(msg
->properties
, CMSG_HASH_DATA_PARAM
,
2234 digestedData
->hash
.pbData
, digestedData
->hash
.cbData
);
2235 LocalFree(digestedData
);
2240 static BOOL
CDecodeMsg_DecodeEnvelopedContent(CDecodeMsg
*msg
,
2241 const CRYPT_DER_BLOB
*blob
)
2244 CRYPT_ENVELOPED_DATA
*envelopedData
;
2247 ret
= CRYPT_AsnDecodePKCSEnvelopedData(blob
->pbData
, blob
->cbData
,
2248 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_ENVELOPED_DATA
*)&envelopedData
,
2251 msg
->u
.enveloped_data
.data
= envelopedData
;
2255 static BOOL
CDecodeMsg_DecodeSignedContent(CDecodeMsg
*msg
,
2256 const CRYPT_DER_BLOB
*blob
)
2259 CRYPT_SIGNED_INFO
*signedInfo
;
2262 ret
= CRYPT_AsnDecodeCMSSignedInfo(blob
->pbData
, blob
->cbData
,
2263 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_SIGNED_INFO
*)&signedInfo
,
2266 msg
->u
.signed_data
.info
= signedInfo
;
2270 /* Decodes the content in blob as the type given, and updates the value
2271 * (type, parameters, etc.) of msg based on what blob contains.
2272 * It doesn't just use msg's type, to allow a recursive call from an implicitly
2273 * typed message once the outer content info has been decoded.
2275 static BOOL
CDecodeMsg_DecodeContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
,
2283 if ((ret
= CDecodeMsg_DecodeDataContent(msg
, blob
)))
2284 msg
->type
= CMSG_DATA
;
2287 if ((ret
= CDecodeMsg_DecodeHashedContent(msg
, blob
)))
2288 msg
->type
= CMSG_HASHED
;
2290 case CMSG_ENVELOPED
:
2291 if ((ret
= CDecodeMsg_DecodeEnvelopedContent(msg
, blob
)))
2292 msg
->type
= CMSG_ENVELOPED
;
2295 if ((ret
= CDecodeMsg_DecodeSignedContent(msg
, blob
)))
2296 msg
->type
= CMSG_SIGNED
;
2300 CRYPT_CONTENT_INFO
*info
;
2303 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
,
2304 msg
->msg_data
.pbData
, msg
->msg_data
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
2305 NULL
, &info
, &size
);
2308 if (!strcmp(info
->pszObjId
, szOID_RSA_data
))
2309 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
, CMSG_DATA
);
2310 else if (!strcmp(info
->pszObjId
, szOID_RSA_digestedData
))
2311 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2313 else if (!strcmp(info
->pszObjId
, szOID_RSA_envelopedData
))
2314 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2316 else if (!strcmp(info
->pszObjId
, szOID_RSA_signedData
))
2317 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2321 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2331 static BOOL
CDecodeMsg_FinalizeHashedContent(CDecodeMsg
*msg
,
2332 CRYPT_DER_BLOB
*blob
)
2334 CRYPT_ALGORITHM_IDENTIFIER
*hashAlgoID
= NULL
;
2339 CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, NULL
, &size
);
2340 hashAlgoID
= CryptMemAlloc(size
);
2341 ret
= CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, hashAlgoID
,
2344 algID
= CertOIDToAlgId(hashAlgoID
->pszObjId
);
2346 if (!msg
->crypt_prov
)
2348 msg
->crypt_prov
= I_CryptGetDefaultCryptProv(algID
);
2349 if (msg
->crypt_prov
)
2350 msg
->base
.open_flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
2353 ret
= CryptCreateHash(msg
->crypt_prov
, algID
, 0, 0, &msg
->u
.hash
);
2356 CRYPT_DATA_BLOB content
;
2358 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2360 /* Unlike for non-detached messages, the data were never stored as
2361 * the content param, but were saved in msg->detached_data instead.
2363 content
.pbData
= msg
->detached_data
.pbData
;
2364 content
.cbData
= msg
->detached_data
.cbData
;
2367 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2368 CMSG_CONTENT_PARAM
, &content
);
2370 ret
= CryptHashData(msg
->u
.hash
, content
.pbData
, content
.cbData
, 0);
2372 CryptMemFree(hashAlgoID
);
2376 static BOOL
CDecodeMsg_FinalizeEnvelopedContent(CDecodeMsg
*msg
,
2377 CRYPT_DER_BLOB
*blob
)
2379 CRYPT_DATA_BLOB
*content
;
2381 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2382 content
= &msg
->detached_data
;
2385 &msg
->u
.enveloped_data
.data
->encryptedContentInfo
.encryptedContent
;
2387 return CRYPT_ConstructBlob(&msg
->u
.enveloped_data
.content
, content
);
2390 static BOOL
CDecodeMsg_FinalizeSignedContent(CDecodeMsg
*msg
,
2391 CRYPT_DER_BLOB
*blob
)
2396 ret
= CSignedMsgData_AllocateHandles(&msg
->u
.signed_data
);
2397 for (i
= 0; ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
2398 ret
= CSignedMsgData_ConstructSignerHandles(&msg
->u
.signed_data
, i
,
2399 &msg
->crypt_prov
, &msg
->base
.open_flags
);
2402 CRYPT_DATA_BLOB
*content
;
2404 /* Now that we have all the content, update the hash handles with
2405 * it. If the message is a detached message, the content is stored
2406 * in msg->detached_data rather than in the signed message's
2409 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2410 content
= &msg
->detached_data
;
2412 content
= &msg
->u
.signed_data
.info
->content
.Content
;
2413 if (content
->cbData
)
2415 /* If the message is not detached, have to decode the message's
2416 * content if the type is szOID_RSA_data.
2418 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) &&
2419 !strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2422 CRYPT_DATA_BLOB
*rsa_blob
;
2424 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
,
2425 X509_OCTET_STRING
, content
->pbData
, content
->cbData
,
2426 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &rsa_blob
, &size
);
2429 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2430 rsa_blob
->pbData
, rsa_blob
->cbData
, TRUE
, Verify
);
2431 LocalFree(rsa_blob
);
2435 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2436 content
->pbData
, content
->cbData
, TRUE
, Verify
);
2442 static BOOL
CDecodeMsg_FinalizeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
2449 ret
= CDecodeMsg_FinalizeHashedContent(msg
, blob
);
2451 case CMSG_ENVELOPED
:
2452 ret
= CDecodeMsg_FinalizeEnvelopedContent(msg
, blob
);
2455 ret
= CDecodeMsg_FinalizeSignedContent(msg
, blob
);
2463 static BOOL
CDecodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
2464 DWORD cbData
, BOOL fFinal
)
2466 CDecodeMsg
*msg
= hCryptMsg
;
2469 TRACE("(%p, %p, %ld, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
2471 if (msg
->base
.state
== MsgStateFinalized
)
2472 SetLastError(CRYPT_E_MSG_ERROR
);
2473 else if (msg
->base
.streamed
)
2475 FIXME("(%p, %p, %ld, %d): streamed update stub\n", hCryptMsg
, pbData
,
2477 switch (msg
->base
.state
)
2480 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2483 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2484 msg
->base
.state
= MsgStateDataFinalized
;
2486 msg
->base
.state
= MsgStateFinalized
;
2489 msg
->base
.state
= MsgStateUpdated
;
2491 case MsgStateUpdated
:
2492 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2495 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2496 msg
->base
.state
= MsgStateDataFinalized
;
2498 msg
->base
.state
= MsgStateFinalized
;
2501 case MsgStateDataFinalized
:
2502 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2504 msg
->base
.state
= MsgStateFinalized
;
2507 SetLastError(CRYPT_E_MSG_ERROR
);
2514 SetLastError(CRYPT_E_MSG_ERROR
);
2517 switch (msg
->base
.state
)
2520 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2521 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2522 msg
->base
.state
= MsgStateDataFinalized
;
2524 msg
->base
.state
= MsgStateFinalized
;
2526 case MsgStateDataFinalized
:
2527 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2528 msg
->base
.state
= MsgStateFinalized
;
2531 SetLastError(CRYPT_E_MSG_ERROR
);
2535 if (ret
&& fFinal
&&
2536 ((msg
->base
.open_flags
& CMSG_DETACHED_FLAG
&& msg
->base
.state
==
2537 MsgStateDataFinalized
) ||
2538 (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->base
.state
==
2539 MsgStateFinalized
)))
2540 ret
= CDecodeMsg_DecodeContent(msg
, &msg
->msg_data
, msg
->type
);
2541 if (ret
&& msg
->base
.state
== MsgStateFinalized
)
2542 ret
= CDecodeMsg_FinalizeContent(msg
, &msg
->msg_data
);
2546 static BOOL
CDecodeHashMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2547 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2551 switch (dwParamType
)
2553 case CMSG_TYPE_PARAM
:
2554 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2556 case CMSG_HASH_ALGORITHM_PARAM
:
2558 CRYPT_DATA_BLOB blob
;
2560 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2564 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2566 CRYPT_FixUpAlgorithmID(pvData
);
2569 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2572 case CMSG_COMPUTED_HASH_PARAM
:
2573 ret
= CryptGetHashParam(msg
->u
.hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
2577 CRYPT_DATA_BLOB blob
;
2579 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2582 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2584 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2590 /* nextData is an in/out parameter - on input it's the memory location in
2591 * which a copy of in's data should be made, and on output it's the memory
2592 * location immediately after out's copy of in's data.
2594 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB
*out
,
2595 const CRYPT_DATA_BLOB
*in
, LPBYTE
*nextData
)
2597 out
->cbData
= in
->cbData
;
2600 out
->pbData
= *nextData
;
2601 memcpy(out
->pbData
, in
->pbData
, in
->cbData
);
2602 *nextData
+= in
->cbData
;
2606 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
2607 const CRYPT_ALGORITHM_IDENTIFIER
*in
, LPBYTE
*nextData
)
2611 out
->pszObjId
= (LPSTR
)*nextData
;
2612 strcpy(out
->pszObjId
, in
->pszObjId
);
2613 *nextData
+= strlen(out
->pszObjId
) + 1;
2615 CRYPT_CopyBlob(&out
->Parameters
, &in
->Parameters
, nextData
);
2618 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES
*out
,
2619 const CRYPT_ATTRIBUTES
*in
, LPBYTE
*nextData
)
2621 out
->cAttr
= in
->cAttr
;
2626 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2627 out
->rgAttr
= (CRYPT_ATTRIBUTE
*)*nextData
;
2628 *nextData
+= in
->cAttr
* sizeof(CRYPT_ATTRIBUTE
);
2629 for (i
= 0; i
< in
->cAttr
; i
++)
2631 if (in
->rgAttr
[i
].pszObjId
)
2633 out
->rgAttr
[i
].pszObjId
= (LPSTR
)*nextData
;
2634 strcpy(out
->rgAttr
[i
].pszObjId
, in
->rgAttr
[i
].pszObjId
);
2635 *nextData
+= strlen(in
->rgAttr
[i
].pszObjId
) + 1;
2637 if (in
->rgAttr
[i
].cValue
)
2641 out
->rgAttr
[i
].cValue
= in
->rgAttr
[i
].cValue
;
2642 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2643 out
->rgAttr
[i
].rgValue
= (PCRYPT_DATA_BLOB
)*nextData
;
2644 *nextData
+= in
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2645 for (j
= 0; j
< in
->rgAttr
[i
].cValue
; j
++)
2646 CRYPT_CopyBlob(&out
->rgAttr
[i
].rgValue
[j
],
2647 &in
->rgAttr
[i
].rgValue
[j
], nextData
);
2653 static DWORD
CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES
*attr
)
2655 DWORD size
= attr
->cAttr
* sizeof(CRYPT_ATTRIBUTE
), i
, j
;
2657 for (i
= 0; i
< attr
->cAttr
; i
++)
2659 if (attr
->rgAttr
[i
].pszObjId
)
2660 size
+= strlen(attr
->rgAttr
[i
].pszObjId
) + 1;
2662 size
= ALIGN_DWORD_PTR(size
);
2663 size
+= attr
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2664 for (j
= 0; j
< attr
->rgAttr
[i
].cValue
; j
++)
2665 size
+= attr
->rgAttr
[i
].rgValue
[j
].cbData
;
2667 /* align pointer again to be conservative */
2668 size
= ALIGN_DWORD_PTR(size
);
2672 static DWORD
CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB
*keyId
)
2674 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2677 CERT_RDN rdn
= { 1, &attr
};
2678 CERT_NAME_INFO name
= { 1, &rdn
};
2680 attr
.pszObjId
= oid_key_rdn
;
2681 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2682 attr
.Value
.cbData
= keyId
->cbData
;
2683 attr
.Value
.pbData
= keyId
->pbData
;
2684 if (CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, NULL
, &size
))
2685 size
++; /* Only include size of special zero serial number on success */
2689 static BOOL
CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB
*issuer
,
2690 CRYPT_INTEGER_BLOB
*serialNumber
, const CRYPT_DATA_BLOB
*keyId
, DWORD encodedLen
,
2693 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2695 CERT_RDN rdn
= { 1, &attr
};
2696 CERT_NAME_INFO name
= { 1, &rdn
};
2699 /* Encode special zero serial number */
2700 serialNumber
->cbData
= 1;
2701 serialNumber
->pbData
= *nextData
;
2705 issuer
->pbData
= *nextData
;
2706 attr
.pszObjId
= oid_key_rdn
;
2707 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2708 attr
.Value
.cbData
= keyId
->cbData
;
2709 attr
.Value
.pbData
= keyId
->pbData
;
2710 ret
= CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, *nextData
,
2714 *nextData
+= encodedLen
;
2715 issuer
->cbData
= encodedLen
;
2720 static BOOL
CRYPT_CopySignerInfo(void *pvData
, DWORD
*pcbData
,
2721 const CMSG_CMS_SIGNER_INFO
*in
)
2723 DWORD size
= sizeof(CMSG_SIGNER_INFO
), rdnSize
= 0;
2726 TRACE("(%p, %ld, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2728 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2730 size
+= in
->SignerId
.IssuerSerialNumber
.Issuer
.cbData
;
2731 size
+= in
->SignerId
.IssuerSerialNumber
.SerialNumber
.cbData
;
2735 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.KeyId
);
2738 if (in
->HashAlgorithm
.pszObjId
)
2739 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2740 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2741 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2742 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2743 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2744 size
+= in
->EncryptedHash
.cbData
;
2746 size
= ALIGN_DWORD_PTR(size
);
2747 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2748 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2753 else if (*pcbData
< size
)
2755 SetLastError(ERROR_MORE_DATA
);
2760 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_SIGNER_INFO
);
2761 CMSG_SIGNER_INFO
*out
= pvData
;
2764 out
->dwVersion
= in
->dwVersion
;
2765 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2767 CRYPT_CopyBlob(&out
->Issuer
,
2768 &in
->SignerId
.IssuerSerialNumber
.Issuer
, &nextData
);
2769 CRYPT_CopyBlob(&out
->SerialNumber
,
2770 &in
->SignerId
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2773 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2774 &in
->SignerId
.KeyId
, rdnSize
, &nextData
);
2777 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2779 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2780 &in
->HashEncryptionAlgorithm
, &nextData
);
2781 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2782 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2783 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2784 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2788 TRACE("returning %d\n", ret
);
2792 static BOOL
CRYPT_CopyCMSSignerInfo(void *pvData
, DWORD
*pcbData
,
2793 const CMSG_CMS_SIGNER_INFO
*in
)
2795 DWORD size
= sizeof(CMSG_CMS_SIGNER_INFO
);
2798 TRACE("(%p, %ld, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2800 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2802 size
+= in
->SignerId
.IssuerSerialNumber
.Issuer
.cbData
;
2803 size
+= in
->SignerId
.IssuerSerialNumber
.SerialNumber
.cbData
;
2806 size
+= in
->SignerId
.KeyId
.cbData
;
2807 if (in
->HashAlgorithm
.pszObjId
)
2808 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2809 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2810 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2811 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2812 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2813 size
+= in
->EncryptedHash
.cbData
;
2815 size
= ALIGN_DWORD_PTR(size
);
2816 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2817 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2823 else if (*pcbData
< size
)
2826 SetLastError(ERROR_MORE_DATA
);
2831 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_CMS_SIGNER_INFO
);
2832 CMSG_CMS_SIGNER_INFO
*out
= pvData
;
2834 out
->dwVersion
= in
->dwVersion
;
2835 out
->SignerId
.dwIdChoice
= in
->SignerId
.dwIdChoice
;
2836 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2838 CRYPT_CopyBlob(&out
->SignerId
.IssuerSerialNumber
.Issuer
,
2839 &in
->SignerId
.IssuerSerialNumber
.Issuer
, &nextData
);
2840 CRYPT_CopyBlob(&out
->SignerId
.IssuerSerialNumber
.SerialNumber
,
2841 &in
->SignerId
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2844 CRYPT_CopyBlob(&out
->SignerId
.KeyId
, &in
->SignerId
.KeyId
, &nextData
);
2845 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2847 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2848 &in
->HashEncryptionAlgorithm
, &nextData
);
2849 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2850 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2851 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2852 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2855 TRACE("returning %d\n", ret
);
2859 static BOOL
CRYPT_CopySignerCertInfo(void *pvData
, DWORD
*pcbData
,
2860 const CMSG_CMS_SIGNER_INFO
*in
)
2862 DWORD size
= sizeof(CERT_INFO
), rdnSize
= 0;
2865 TRACE("(%p, %ld, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2867 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2869 size
+= in
->SignerId
.IssuerSerialNumber
.Issuer
.cbData
;
2870 size
+= in
->SignerId
.IssuerSerialNumber
.SerialNumber
.cbData
;
2874 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.KeyId
);
2882 else if (*pcbData
< size
)
2885 SetLastError(ERROR_MORE_DATA
);
2890 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2891 CERT_INFO
*out
= pvData
;
2893 memset(out
, 0, sizeof(CERT_INFO
));
2894 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2896 CRYPT_CopyBlob(&out
->Issuer
,
2897 &in
->SignerId
.IssuerSerialNumber
.Issuer
, &nextData
);
2898 CRYPT_CopyBlob(&out
->SerialNumber
,
2899 &in
->SignerId
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2903 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2904 &in
->SignerId
.KeyId
, rdnSize
, &nextData
);
2906 TRACE("returning %d\n", ret
);
2910 static BOOL
CRYPT_CopyRecipientInfo(void *pvData
, DWORD
*pcbData
,
2911 const CERT_ISSUER_SERIAL_NUMBER
*in
)
2913 DWORD size
= sizeof(CERT_INFO
);
2916 TRACE("(%p, %ld, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2918 size
+= in
->SerialNumber
.cbData
;
2919 size
+= in
->Issuer
.cbData
;
2925 else if (*pcbData
< size
)
2928 SetLastError(ERROR_MORE_DATA
);
2933 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2934 CERT_INFO
*out
= pvData
;
2936 CRYPT_CopyBlob(&out
->SerialNumber
, &in
->SerialNumber
, &nextData
);
2937 CRYPT_CopyBlob(&out
->Issuer
, &in
->Issuer
, &nextData
);
2940 TRACE("returning %d\n", ret
);
2944 static BOOL
CDecodeEnvelopedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2945 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2949 switch (dwParamType
)
2951 case CMSG_TYPE_PARAM
:
2952 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2954 case CMSG_CONTENT_PARAM
:
2955 if (msg
->u
.enveloped_data
.data
)
2956 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2957 msg
->u
.enveloped_data
.content
.pbData
,
2958 msg
->u
.enveloped_data
.content
.cbData
);
2960 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2962 case CMSG_RECIPIENT_COUNT_PARAM
:
2963 if (msg
->u
.enveloped_data
.data
)
2964 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2965 &msg
->u
.enveloped_data
.data
->cRecipientInfo
, sizeof(DWORD
));
2967 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2969 case CMSG_RECIPIENT_INFO_PARAM
:
2970 if (msg
->u
.enveloped_data
.data
)
2972 if (dwIndex
< msg
->u
.enveloped_data
.data
->cRecipientInfo
)
2974 PCMSG_KEY_TRANS_RECIPIENT_INFO recipientInfo
=
2975 &msg
->u
.enveloped_data
.data
->rgRecipientInfo
[dwIndex
];
2977 ret
= CRYPT_CopyRecipientInfo(pvData
, pcbData
,
2978 &recipientInfo
->RecipientId
.IssuerSerialNumber
);
2981 SetLastError(CRYPT_E_INVALID_INDEX
);
2984 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2987 FIXME("unimplemented for %ld\n", dwParamType
);
2988 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2993 static BOOL
CRYPT_CopyAttr(void *pvData
, DWORD
*pcbData
, const CRYPT_ATTRIBUTES
*attr
)
2998 TRACE("(%p, %ld, %p)\n", pvData
, pvData
? *pcbData
: 0, attr
);
3000 size
= CRYPT_SizeOfAttributes(attr
);
3006 else if (*pcbData
< size
)
3009 SetLastError(ERROR_MORE_DATA
);
3013 ret
= CRYPT_ConstructAttributes(pvData
, attr
);
3015 TRACE("returning %d\n", ret
);
3019 static BOOL
CDecodeSignedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
3020 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3024 switch (dwParamType
)
3026 case CMSG_TYPE_PARAM
:
3027 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
3029 case CMSG_CONTENT_PARAM
:
3030 if (msg
->u
.signed_data
.info
)
3032 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
3035 CRYPT_DATA_BLOB
*blob
;
3038 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
3039 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
3040 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
3041 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &blob
, &size
);
3044 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
->pbData
,
3050 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3051 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
3052 msg
->u
.signed_data
.info
->content
.Content
.cbData
);
3055 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3057 case CMSG_INNER_CONTENT_TYPE_PARAM
:
3058 if (msg
->u
.signed_data
.info
)
3059 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3060 msg
->u
.signed_data
.info
->content
.pszObjId
,
3061 strlen(msg
->u
.signed_data
.info
->content
.pszObjId
) + 1);
3063 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3065 case CMSG_SIGNER_COUNT_PARAM
:
3066 if (msg
->u
.signed_data
.info
)
3067 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3068 &msg
->u
.signed_data
.info
->cSignerInfo
, sizeof(DWORD
));
3070 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3072 case CMSG_SIGNER_INFO_PARAM
:
3073 if (msg
->u
.signed_data
.info
)
3075 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3076 SetLastError(CRYPT_E_INVALID_INDEX
);
3078 ret
= CRYPT_CopySignerInfo(pvData
, pcbData
,
3079 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3082 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3084 case CMSG_SIGNER_CERT_INFO_PARAM
:
3085 if (msg
->u
.signed_data
.info
)
3087 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3088 SetLastError(CRYPT_E_INVALID_INDEX
);
3090 ret
= CRYPT_CopySignerCertInfo(pvData
, pcbData
,
3091 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3094 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3096 case CMSG_CERT_COUNT_PARAM
:
3097 if (msg
->u
.signed_data
.info
)
3098 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3099 &msg
->u
.signed_data
.info
->cCertEncoded
, sizeof(DWORD
));
3101 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3103 case CMSG_CERT_PARAM
:
3104 if (msg
->u
.signed_data
.info
)
3106 if (dwIndex
>= msg
->u
.signed_data
.info
->cCertEncoded
)
3107 SetLastError(CRYPT_E_INVALID_INDEX
);
3109 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3110 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].pbData
,
3111 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].cbData
);
3114 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3116 case CMSG_CRL_COUNT_PARAM
:
3117 if (msg
->u
.signed_data
.info
)
3118 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3119 &msg
->u
.signed_data
.info
->cCrlEncoded
, sizeof(DWORD
));
3121 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3123 case CMSG_CRL_PARAM
:
3124 if (msg
->u
.signed_data
.info
)
3126 if (dwIndex
>= msg
->u
.signed_data
.info
->cCrlEncoded
)
3127 SetLastError(CRYPT_E_INVALID_INDEX
);
3129 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3130 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].pbData
,
3131 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].cbData
);
3134 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3136 case CMSG_COMPUTED_HASH_PARAM
:
3137 if (msg
->u
.signed_data
.info
)
3139 if (dwIndex
>= msg
->u
.signed_data
.cSignerHandle
)
3140 SetLastError(CRYPT_E_INVALID_INDEX
);
3142 ret
= CryptGetHashParam(
3143 msg
->u
.signed_data
.signerHandles
[dwIndex
].contentHash
,
3144 HP_HASHVAL
, pvData
, pcbData
, 0);
3147 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3149 case CMSG_ENCODED_MESSAGE
:
3150 if (msg
->msg_data
.pbData
)
3151 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->msg_data
.pbData
, msg
->msg_data
.cbData
);
3153 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3155 case CMSG_ENCODED_SIGNER
:
3156 if (msg
->u
.signed_data
.info
)
3158 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3159 SetLastError(CRYPT_E_INVALID_INDEX
);
3161 ret
= CryptEncodeObjectEx(
3162 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, CMS_SIGNER_INFO
,
3163 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
], 0, NULL
,
3167 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3169 case CMSG_ATTR_CERT_COUNT_PARAM
:
3170 if (msg
->u
.signed_data
.info
)
3172 DWORD attrCertCount
= 0;
3174 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3175 &attrCertCount
, sizeof(DWORD
));
3178 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3180 case CMSG_ATTR_CERT_PARAM
:
3181 if (msg
->u
.signed_data
.info
)
3182 SetLastError(CRYPT_E_INVALID_INDEX
);
3184 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3186 case CMSG_CMS_SIGNER_INFO_PARAM
:
3187 if (msg
->u
.signed_data
.info
)
3189 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3190 SetLastError(CRYPT_E_INVALID_INDEX
);
3192 ret
= CRYPT_CopyCMSSignerInfo(pvData
, pcbData
,
3193 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3196 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3198 case CMSG_SIGNER_AUTH_ATTR_PARAM
:
3199 if (msg
->u
.signed_data
.info
)
3201 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3202 SetLastError(CRYPT_E_INVALID_INDEX
);
3204 ret
= CRYPT_CopyAttr(pvData
, pcbData
,
3205 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
].AuthAttrs
);
3208 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3210 case CMSG_SIGNER_UNAUTH_ATTR_PARAM
:
3211 if (msg
->u
.signed_data
.info
)
3213 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3214 SetLastError(CRYPT_E_INVALID_INDEX
);
3216 ret
= CRYPT_CopyAttr(pvData
, pcbData
,
3217 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
].UnauthAttrs
);
3220 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3223 FIXME("unimplemented for %ld\n", dwParamType
);
3224 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3229 static BOOL
CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
3230 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3232 CDecodeMsg
*msg
= hCryptMsg
;
3238 ret
= CDecodeHashMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3241 case CMSG_ENVELOPED
:
3242 ret
= CDecodeEnvelopedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3246 ret
= CDecodeSignedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3250 switch (dwParamType
)
3252 case CMSG_TYPE_PARAM
:
3253 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
,
3258 CRYPT_DATA_BLOB blob
;
3260 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
3263 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
,
3266 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3273 static BOOL
CDecodeHashMsg_VerifyHash(CDecodeMsg
*msg
)
3276 CRYPT_DATA_BLOB hashBlob
;
3278 ret
= ContextPropertyList_FindProperty(msg
->properties
,
3279 CMSG_HASH_DATA_PARAM
, &hashBlob
);
3282 DWORD computedHashSize
= 0;
3284 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
,
3286 if (hashBlob
.cbData
== computedHashSize
)
3288 LPBYTE computedHash
= CryptMemAlloc(computedHashSize
);
3292 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
3293 computedHash
, &computedHashSize
);
3296 if (memcmp(hashBlob
.pbData
, computedHash
, hashBlob
.cbData
))
3298 SetLastError(CRYPT_E_HASH_VALUE
);
3302 CryptMemFree(computedHash
);
3306 SetLastError(ERROR_OUTOFMEMORY
);
3312 SetLastError(CRYPT_E_HASH_VALUE
);
3319 static BOOL
cng_verify_msg_signature(CMSG_CMS_SIGNER_INFO
*signer
, HCRYPTHASH hash
, CERT_PUBLIC_KEY_INFO
*key_info
)
3321 BYTE
*hash_value
, *sig_value
= NULL
;
3322 DWORD hash_len
, sig_len
;
3323 BCRYPT_KEY_HANDLE key
;
3327 if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING
, key_info
, 0, NULL
, &key
)) return FALSE
;
3328 if (!extract_hash(hash
, &hash_value
, &hash_len
)) goto done
;
3329 if (!cng_prepare_signature(key_info
->Algorithm
.pszObjId
, signer
->EncryptedHash
.pbData
,
3330 signer
->EncryptedHash
.cbData
, &sig_value
, &sig_len
)) goto done
;
3331 status
= BCryptVerifySignature(key
, NULL
, hash_value
, hash_len
, sig_value
, sig_len
, 0);
3334 FIXME("Failed to verify signature: %08lx.\n", status
);
3335 SetLastError(RtlNtStatusToDosError(status
));
3339 CryptMemFree(sig_value
);
3340 CryptMemFree(hash_value
);
3341 BCryptDestroyKey(key
);
3345 static BOOL
CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg
*msg
,
3346 HCRYPTPROV prov
, DWORD signerIndex
, PCERT_PUBLIC_KEY_INFO keyInfo
)
3353 if (msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
)
3354 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].authAttrHash
;
3356 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].contentHash
;
3358 if (keyInfo
->Algorithm
.pszObjId
) alg_id
= CertOIDToAlgId(keyInfo
->Algorithm
.pszObjId
);
3359 if (alg_id
== CALG_OID_INFO_PARAMETERS
|| alg_id
== CALG_OID_INFO_CNG_ONLY
)
3360 return cng_verify_msg_signature(&msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
], hash
, keyInfo
);
3363 prov
= msg
->crypt_prov
;
3364 ret
= CryptImportPublicKeyInfo(prov
, X509_ASN_ENCODING
, keyInfo
, &key
);
3367 CRYPT_HASH_BLOB reversedHash
;
3369 ret
= CRYPT_ConstructBlob(&reversedHash
,
3370 &msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].EncryptedHash
);
3373 CRYPT_ReverseBytes(&reversedHash
);
3374 ret
= CryptVerifySignatureW(hash
, reversedHash
.pbData
,
3375 reversedHash
.cbData
, key
, NULL
, 0);
3376 CryptMemFree(reversedHash
.pbData
);
3378 CryptDestroyKey(key
);
3383 static BOOL
CDecodeSignedMsg_VerifySignature(CDecodeMsg
*msg
, PCERT_INFO info
)
3388 if (!msg
->u
.signed_data
.signerHandles
)
3390 SetLastError(NTE_BAD_SIGNATURE
);
3393 for (i
= 0; !ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
3395 PCMSG_CMS_SIGNER_INFO signerInfo
=
3396 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
];
3398 if (signerInfo
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
3400 ret
= CertCompareCertificateName(X509_ASN_ENCODING
,
3401 &signerInfo
->SignerId
.IssuerSerialNumber
.Issuer
,
3405 ret
= CertCompareIntegerBlob(
3406 &signerInfo
->SignerId
.IssuerSerialNumber
.SerialNumber
,
3407 &info
->SerialNumber
);
3414 FIXME("signer %ld: unimplemented for key id\n", i
);
3418 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, 0, i
,
3419 &info
->SubjectPublicKeyInfo
);
3421 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3426 static BOOL
CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg
*msg
,
3427 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para
)
3431 if (para
->cbSize
!= sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
))
3432 SetLastError(ERROR_INVALID_PARAMETER
);
3433 else if (para
->dwSignerIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3434 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3435 else if (!msg
->u
.signed_data
.signerHandles
)
3436 SetLastError(NTE_BAD_SIGNATURE
);
3439 switch (para
->dwSignerType
)
3441 case CMSG_VERIFY_SIGNER_PUBKEY
:
3442 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
,
3443 para
->hCryptProv
, para
->dwSignerIndex
, para
->pvSigner
);
3445 case CMSG_VERIFY_SIGNER_CERT
:
3447 PCCERT_CONTEXT cert
= para
->pvSigner
;
3449 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, para
->hCryptProv
,
3450 para
->dwSignerIndex
, &cert
->pCertInfo
->SubjectPublicKeyInfo
);
3454 FIXME("unimplemented for signer type %ld\n", para
->dwSignerType
);
3455 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3461 static BOOL WINAPI
CRYPT_ImportKeyTrans(
3462 PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm
,
3463 PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara
, DWORD dwFlags
,
3464 void *pvReserved
, HCRYPTKEY
*phContentEncryptKey
)
3469 ret
= CryptGetUserKey(pKeyTransDecryptPara
->hCryptProv
,
3470 pKeyTransDecryptPara
->dwKeySpec
? pKeyTransDecryptPara
->dwKeySpec
:
3471 AT_KEYEXCHANGE
, &key
);
3474 CMSG_KEY_TRANS_RECIPIENT_INFO
*info
=
3475 &pKeyTransDecryptPara
->pKeyTrans
[pKeyTransDecryptPara
->dwRecipientIndex
];
3476 CRYPT_DATA_BLOB
*encryptedKey
= &info
->EncryptedKey
;
3477 DWORD size
= encryptedKey
->cbData
+ sizeof(BLOBHEADER
) + sizeof(ALG_ID
);
3478 BYTE
*keyBlob
= CryptMemAlloc(size
);
3482 DWORD i
, k
= size
- 1;
3483 BLOBHEADER
*blobHeader
= (BLOBHEADER
*)keyBlob
;
3484 ALG_ID
*algID
= (ALG_ID
*)(keyBlob
+ sizeof(BLOBHEADER
));
3486 blobHeader
->bType
= SIMPLEBLOB
;
3487 blobHeader
->bVersion
= CUR_BLOB_VERSION
;
3488 blobHeader
->reserved
= 0;
3489 blobHeader
->aiKeyAlg
= CertOIDToAlgId(
3490 pContentEncryptionAlgorithm
->pszObjId
);
3491 *algID
= CertOIDToAlgId(info
->KeyEncryptionAlgorithm
.pszObjId
);
3492 for (i
= 0; i
< encryptedKey
->cbData
; ++i
, --k
)
3493 keyBlob
[k
] = encryptedKey
->pbData
[i
];
3495 ret
= CryptImportKey(pKeyTransDecryptPara
->hCryptProv
, keyBlob
,
3496 size
, key
, 0, phContentEncryptKey
);
3497 CryptMemFree(keyBlob
);
3501 CryptDestroyKey(key
);
3506 static BOOL
CRYPT_ImportEncryptedKey(PCRYPT_ALGORITHM_IDENTIFIER contEncrAlg
,
3507 PCMSG_CTRL_DECRYPT_PARA para
, PCMSG_KEY_TRANS_RECIPIENT_INFO info
,
3510 static HCRYPTOIDFUNCSET set
= NULL
;
3511 PFN_CMSG_IMPORT_KEY_TRANS importKeyFunc
= NULL
;
3512 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3513 CMSG_CTRL_KEY_TRANS_DECRYPT_PARA decryptPara
;
3516 memset(&decryptPara
, 0, sizeof(decryptPara
));
3517 decryptPara
.cbSize
= sizeof(decryptPara
);
3518 decryptPara
.hCryptProv
= para
->hCryptProv
;
3519 decryptPara
.dwKeySpec
= para
->dwKeySpec
;
3520 decryptPara
.pKeyTrans
= info
;
3521 decryptPara
.dwRecipientIndex
= para
->dwRecipientIndex
;
3524 set
= CryptInitOIDFunctionSet(CMSG_OID_IMPORT_KEY_TRANS_FUNC
, 0);
3525 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
, contEncrAlg
->pszObjId
, 0,
3526 (void **)&importKeyFunc
, &hFunc
);
3528 importKeyFunc
= CRYPT_ImportKeyTrans
;
3529 ret
= importKeyFunc(contEncrAlg
, &decryptPara
, 0, NULL
, key
);
3531 CryptFreeOIDFunctionAddress(hFunc
, 0);
3535 static BOOL
CDecodeEnvelopedMsg_CrtlDecrypt(CDecodeMsg
*msg
,
3536 PCMSG_CTRL_DECRYPT_PARA para
)
3539 CEnvelopedDecodeMsg
*enveloped_data
= &msg
->u
.enveloped_data
;
3540 CRYPT_ENVELOPED_DATA
*data
= enveloped_data
->data
;
3542 if (para
->cbSize
!= sizeof(CMSG_CTRL_DECRYPT_PARA
))
3543 SetLastError(E_INVALIDARG
);
3545 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3546 else if (para
->dwRecipientIndex
>= data
->cRecipientInfo
)
3547 SetLastError(CRYPT_E_INVALID_INDEX
);
3548 else if (enveloped_data
->decrypted
)
3549 SetLastError(CRYPT_E_ALREADY_DECRYPTED
);
3550 else if (!para
->hCryptProv
)
3551 SetLastError(ERROR_INVALID_PARAMETER
);
3552 else if (enveloped_data
->content
.cbData
)
3556 ret
= CRYPT_ImportEncryptedKey(
3557 &data
->encryptedContentInfo
.contentEncryptionAlgorithm
, para
,
3558 data
->rgRecipientInfo
, &key
);
3561 ret
= CryptDecrypt(key
, 0, TRUE
, 0, enveloped_data
->content
.pbData
,
3562 &enveloped_data
->content
.cbData
);
3563 CryptDestroyKey(key
);
3569 enveloped_data
->decrypted
= TRUE
;
3573 static BOOL
CDecodeMsg_Control(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3574 DWORD dwCtrlType
, const void *pvCtrlPara
)
3576 CDecodeMsg
*msg
= hCryptMsg
;
3581 case CMSG_CTRL_VERIFY_SIGNATURE
:
3585 ret
= CDecodeSignedMsg_VerifySignature(msg
, (PCERT_INFO
)pvCtrlPara
);
3588 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3591 case CMSG_CTRL_DECRYPT
:
3594 case CMSG_ENVELOPED
:
3595 ret
= CDecodeEnvelopedMsg_CrtlDecrypt(msg
,
3596 (PCMSG_CTRL_DECRYPT_PARA
)pvCtrlPara
);
3597 if (ret
&& (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
))
3598 msg
->u
.enveloped_data
.crypt_prov
=
3599 ((PCMSG_CTRL_DECRYPT_PARA
)pvCtrlPara
)->hCryptProv
;
3602 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3605 case CMSG_CTRL_VERIFY_HASH
:
3609 ret
= CDecodeHashMsg_VerifyHash(msg
);
3612 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3615 case CMSG_CTRL_VERIFY_SIGNATURE_EX
:
3619 ret
= CDecodeSignedMsg_VerifySignatureEx(msg
,
3620 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
)pvCtrlPara
);
3623 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3627 SetLastError(CRYPT_E_CONTROL_TYPE
);
3632 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
3633 DWORD dwMsgType
, HCRYPTPROV_LEGACY hCryptProv
, PCERT_INFO pRecipientInfo
,
3634 PCMSG_STREAM_INFO pStreamInfo
)
3638 TRACE("(%08lx, %08lx, %08lx, %08Ix, %p, %p)\n", dwMsgEncodingType
,
3639 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
3641 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
3643 SetLastError(E_INVALIDARG
);
3646 msg
= CryptMemAlloc(sizeof(CDecodeMsg
));
3649 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
3650 CDecodeMsg_Close
, CDecodeMsg_GetParam
, CDecodeMsg_Update
,
3651 CDecodeMsg_Control
);
3652 msg
->type
= dwMsgType
;
3653 msg
->crypt_prov
= hCryptProv
;
3654 memset(&msg
->u
, 0, sizeof(msg
->u
));
3655 msg
->msg_data
.cbData
= 0;
3656 msg
->msg_data
.pbData
= NULL
;
3657 msg
->detached_data
.cbData
= 0;
3658 msg
->detached_data
.pbData
= NULL
;
3659 msg
->properties
= ContextPropertyList_Create();
3664 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
3666 TRACE("(%p)\n", hCryptMsg
);
3670 CryptMsgBase
*msg
= hCryptMsg
;
3672 InterlockedIncrement(&msg
->ref
);
3677 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
3679 TRACE("(%p)\n", hCryptMsg
);
3683 CryptMsgBase
*msg
= hCryptMsg
;
3685 if (InterlockedDecrement(&msg
->ref
) == 0)
3687 TRACE("freeing %p\n", msg
);
3696 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
3697 DWORD cbData
, BOOL fFinal
)
3699 CryptMsgBase
*msg
= hCryptMsg
;
3701 TRACE("(%p, %p, %ld, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
3703 return msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
3706 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
3707 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3709 CryptMsgBase
*msg
= hCryptMsg
;
3711 TRACE("(%p, %ld, %ld, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
3713 return msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);
3716 BOOL WINAPI
CryptMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3717 DWORD dwCtrlType
, const void *pvCtrlPara
)
3719 CryptMsgBase
*msg
= hCryptMsg
;
3721 TRACE("(%p, %08lx, %ld, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
,
3723 return msg
->control(hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
3726 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
3727 DWORD dwSignerIndex
)
3729 CERT_INFO
*certInfo
= NULL
;
3732 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
3735 certInfo
= CryptMemAlloc(size
);
3738 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
3739 dwSignerIndex
, certInfo
, &size
))
3741 CryptMemFree(certInfo
);
3749 BOOL WINAPI
CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg
, DWORD cSignerStore
,
3750 HCERTSTORE
*rghSignerStore
, DWORD dwFlags
, PCCERT_CONTEXT
*ppSigner
,
3751 DWORD
*pdwSignerIndex
)
3754 DWORD i
, signerIndex
= 0;
3755 PCCERT_CONTEXT signerCert
= NULL
;
3758 TRACE("(%p, %ld, %p, %08lx, %p, %p)\n", hCryptMsg
, cSignerStore
,
3759 rghSignerStore
, dwFlags
, ppSigner
, pdwSignerIndex
);
3761 /* Clear output parameters */
3764 if (pdwSignerIndex
&& !(dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
))
3765 *pdwSignerIndex
= 0;
3767 /* Create store to search for signer certificates */
3768 store
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
3769 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
3770 if (!(dwFlags
& CMSG_TRUSTED_SIGNER_FLAG
))
3772 HCERTSTORE msgStore
= CertOpenStore(CERT_STORE_PROV_MSG
, 0, 0, 0,
3775 CertAddStoreToCollection(store
, msgStore
, 0, 0);
3776 CertCloseStore(msgStore
, 0);
3778 for (i
= 0; i
< cSignerStore
; i
++)
3779 CertAddStoreToCollection(store
, rghSignerStore
[i
], 0, 0);
3781 /* Find signer cert */
3782 if (dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
)
3784 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3789 signerIndex
= *pdwSignerIndex
;
3790 signerCert
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
,
3791 0, CERT_FIND_SUBJECT_CERT
, signer
, NULL
);
3792 CryptMemFree(signer
);
3797 DWORD count
, size
= sizeof(count
);
3799 if (CryptMsgGetParam(hCryptMsg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
,
3802 for (i
= 0; !signerCert
&& i
< count
; i
++)
3804 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3809 signerCert
= CertFindCertificateInStore(store
,
3810 X509_ASN_ENCODING
, 0, CERT_FIND_SUBJECT_CERT
, signer
,
3814 CryptMemFree(signer
);
3819 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER
);
3823 if (!(dwFlags
& CMSG_SIGNER_ONLY_FLAG
))
3824 ret
= CryptMsgControl(hCryptMsg
, 0, CMSG_CTRL_VERIFY_SIGNATURE
,
3825 signerCert
->pCertInfo
);
3831 *ppSigner
= CertDuplicateCertificateContext(signerCert
);
3833 *pdwSignerIndex
= signerIndex
;
3835 CertFreeCertificateContext(signerCert
);
3838 CertCloseStore(store
, 0);
3842 BOOL WINAPI
CryptMsgVerifyCountersignatureEncoded(HCRYPTPROV_LEGACY hCryptProv
,
3843 DWORD dwEncodingType
, BYTE
*pbSignerInfo
, DWORD cbSignerInfo
,
3844 PBYTE pbSignerInfoCountersignature
, DWORD cbSignerInfoCountersignature
,
3845 CERT_INFO
*pciCountersigner
)
3847 FIXME("(%08Ix, %08lx, %p, %ld, %p, %ld, %p): stub\n", hCryptProv
,
3848 dwEncodingType
, pbSignerInfo
, cbSignerInfo
, pbSignerInfoCountersignature
,
3849 cbSignerInfoCountersignature
, pciCountersigner
);
3853 BOOL WINAPI
CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv
,
3854 DWORD dwEncodingType
, PBYTE pbSignerInfo
, DWORD cbSignerInfo
,
3855 PBYTE pbSignerInfoCountersignature
, DWORD cbSignerInfoCountersignature
,
3856 DWORD dwSignerType
, void *pvSigner
, DWORD dwFlags
, void *pvReserved
)
3858 FIXME("(%08Ix, %08lx, %p, %ld, %p, %ld, %ld, %p, %08lx, %p): stub\n", hCryptProv
,
3859 dwEncodingType
, pbSignerInfo
, cbSignerInfo
, pbSignerInfoCountersignature
,
3860 cbSignerInfoCountersignature
, dwSignerType
, pvSigner
, dwFlags
, pvReserved
);
3864 BOOL WINAPI
CryptMsgEncodeAndSignCTL(DWORD dwMsgEncodingType
,
3865 PCTL_INFO pCtlInfo
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3866 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3872 TRACE("(%08lx, %p, %p, %08lx, %p, %p)\n", dwMsgEncodingType
, pCtlInfo
,
3873 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3877 FIXME("unimplemented for flags %08lx\n", dwFlags
);
3880 if ((ret
= CryptEncodeObjectEx(dwMsgEncodingType
, PKCS_CTL
, pCtlInfo
,
3881 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &pbCtlContent
, &cbCtlContent
)))
3883 ret
= CryptMsgSignCTL(dwMsgEncodingType
, pbCtlContent
, cbCtlContent
,
3884 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3885 LocalFree(pbCtlContent
);
3890 BOOL WINAPI
CryptMsgSignCTL(DWORD dwMsgEncodingType
, BYTE
*pbCtlContent
,
3891 DWORD cbCtlContent
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3892 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3894 static char oid_ctl
[] = szOID_CTL
;
3898 TRACE("(%08lx, %p, %ld, %p, %08lx, %p, %p)\n", dwMsgEncodingType
,
3899 pbCtlContent
, cbCtlContent
, pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3903 FIXME("unimplemented for flags %08lx\n", dwFlags
);
3906 msg
= CryptMsgOpenToEncode(dwMsgEncodingType
, 0, CMSG_SIGNED
, pSignInfo
,
3910 ret
= CryptMsgUpdate(msg
, pbCtlContent
, cbCtlContent
, TRUE
);
3912 ret
= CryptMsgGetParam(msg
, CMSG_CONTENT_PARAM
, 0, pbEncoded
,