2 * Copyright 2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/port.h"
23 #define NONAMELESSUNION
29 #include "wine/debug.h"
30 #include "wine/exception.h"
31 #include "crypt32_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
35 /* Called when a message's ref count reaches zero. Free any message-specific
38 typedef void (*CryptMsgCloseFunc
)(HCRYPTMSG msg
);
40 typedef BOOL (*CryptMsgGetParamFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
41 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
);
43 typedef BOOL (*CryptMsgUpdateFunc
)(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
44 DWORD cbData
, BOOL fFinal
);
46 typedef BOOL (*CryptMsgControlFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
47 DWORD dwCtrlType
, const void *pvCtrlPara
);
49 static BOOL
CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
50 DWORD dwCtrlType
, const void *pvCtrlPara
)
52 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
53 SetLastError(E_INVALIDARG
);
57 typedef enum _CryptMsgState
{
60 MsgStateDataFinalized
,
64 typedef struct _CryptMsgBase
69 CMSG_STREAM_INFO stream_info
;
71 CryptMsgCloseFunc close
;
72 CryptMsgUpdateFunc update
;
73 CryptMsgGetParamFunc get_param
;
74 CryptMsgControlFunc control
;
77 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
78 PCMSG_STREAM_INFO pStreamInfo
, CryptMsgCloseFunc close
,
79 CryptMsgGetParamFunc get_param
, CryptMsgUpdateFunc update
,
80 CryptMsgControlFunc control
)
83 msg
->open_flags
= dwFlags
;
87 msg
->stream_info
= *pStreamInfo
;
91 msg
->streamed
= FALSE
;
92 memset(&msg
->stream_info
, 0, sizeof(msg
->stream_info
));
95 msg
->get_param
= get_param
;
97 msg
->control
= control
;
98 msg
->state
= MsgStateInit
;
101 typedef struct _CDataEncodeMsg
104 DWORD bare_content_len
;
108 static const BYTE empty_data_content
[] = { 0x04,0x00 };
110 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
112 CDataEncodeMsg
*msg
= hCryptMsg
;
114 if (msg
->bare_content
!= empty_data_content
)
115 LocalFree(msg
->bare_content
);
118 static BOOL WINAPI
CRYPT_EncodeContentLength(DWORD dwCertEncodingType
,
119 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
120 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
122 DWORD dataLen
= *(DWORD
*)pvStructInfo
;
126 /* Trick: report bytes needed based on total message length, even though
127 * the message isn't available yet. The caller will use the length
128 * reported here to encode its length.
130 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
132 *pcbEncoded
= 1 + lenBytes
+ dataLen
;
135 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
136 pcbEncoded
, 1 + lenBytes
)))
138 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
139 pbEncoded
= *(BYTE
**)pbEncoded
;
140 *pbEncoded
++ = ASN_OCTETSTRING
;
141 CRYPT_EncodeLen(dataLen
, pbEncoded
,
148 static BOOL
CRYPT_EncodeDataContentInfoHeader(const CDataEncodeMsg
*msg
,
149 CRYPT_DATA_BLOB
*header
)
153 if (msg
->base
.streamed
&& msg
->base
.stream_info
.cbContent
== 0xffffffff)
155 static const BYTE headerValue
[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
156 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
158 header
->pbData
= LocalAlloc(0, sizeof(headerValue
));
161 header
->cbData
= sizeof(headerValue
);
162 memcpy(header
->pbData
, headerValue
, sizeof(headerValue
));
170 struct AsnConstructedItem constructed
= { 0,
171 &msg
->base
.stream_info
.cbContent
, CRYPT_EncodeContentLength
};
172 struct AsnEncodeSequenceItem items
[2] = {
173 { szOID_RSA_data
, CRYPT_AsnEncodeOid
, 0 },
174 { &constructed
, CRYPT_AsnEncodeConstructed
, 0 },
177 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
178 sizeof(items
) / sizeof(items
[0]), CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
179 (LPBYTE
)&header
->pbData
, &header
->cbData
);
182 /* Trick: subtract the content length from the reported length,
183 * as the actual content hasn't come yet.
185 header
->cbData
-= msg
->base
.stream_info
.cbContent
;
191 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
192 DWORD cbData
, BOOL fFinal
)
194 CDataEncodeMsg
*msg
= hCryptMsg
;
197 if (msg
->base
.state
== MsgStateFinalized
)
198 SetLastError(CRYPT_E_MSG_ERROR
);
199 else if (msg
->base
.streamed
)
203 if (msg
->base
.state
!= MsgStateUpdated
)
205 CRYPT_DATA_BLOB header
;
207 ret
= CRYPT_EncodeDataContentInfoHeader(msg
, &header
);
210 ret
= msg
->base
.stream_info
.pfnStreamOutput(
211 msg
->base
.stream_info
.pvArg
, header
.pbData
, header
.cbData
,
213 LocalFree(header
.pbData
);
216 /* Curiously, every indefinite-length streamed update appears to
217 * get its own tag and length, regardless of fFinal.
219 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
224 ret
= CRYPT_EncodeContentLength(X509_ASN_ENCODING
, NULL
,
225 &cbData
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (BYTE
*)&header
,
229 ret
= msg
->base
.stream_info
.pfnStreamOutput(
230 msg
->base
.stream_info
.pvArg
, header
, headerLen
,
237 ret
= msg
->base
.stream_info
.pfnStreamOutput(
238 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
240 msg
->base
.state
= MsgStateUpdated
;
244 msg
->base
.state
= MsgStateFinalized
;
245 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
247 BYTE indefinite_trailer
[6] = { 0 };
249 ret
= msg
->base
.stream_info
.pfnStreamOutput(
250 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
253 ret
= msg
->base
.stream_info
.pfnStreamOutput(
254 msg
->base
.stream_info
.pvArg
, indefinite_trailer
,
255 sizeof(indefinite_trailer
), TRUE
);
258 ret
= msg
->base
.stream_info
.pfnStreamOutput(
259 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
, TRUE
);
264 SetLastError(STATUS_ACCESS_VIOLATION
);
273 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
274 SetLastError(E_INVALIDARG
);
276 SetLastError(CRYPT_E_MSG_ERROR
);
280 msg
->base
.state
= MsgStateFinalized
;
282 SetLastError(E_INVALIDARG
);
285 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
287 /* non-streamed data messages don't allow non-final updates,
288 * don't bother checking whether data already exist, they can't.
290 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
291 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
292 &msg
->bare_content_len
);
299 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
306 else if (*pcbData
< len
)
309 SetLastError(ERROR_MORE_DATA
);
315 memcpy(pvData
, src
, len
);
320 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
321 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
323 CDataEncodeMsg
*msg
= hCryptMsg
;
328 case CMSG_CONTENT_PARAM
:
329 if (msg
->base
.streamed
)
330 SetLastError(E_INVALIDARG
);
333 CRYPT_CONTENT_INFO info
;
334 char rsa_data
[] = "1.2.840.113549.1.7.1";
336 info
.pszObjId
= rsa_data
;
337 info
.Content
.cbData
= msg
->bare_content_len
;
338 info
.Content
.pbData
= msg
->bare_content
;
339 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
343 case CMSG_BARE_CONTENT_PARAM
:
344 if (msg
->base
.streamed
)
345 SetLastError(E_INVALIDARG
);
347 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->bare_content
,
348 msg
->bare_content_len
);
351 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
356 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
357 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
363 SetLastError(E_INVALIDARG
);
366 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
369 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
370 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
,
371 CRYPT_DefaultMsgControl
);
372 msg
->bare_content_len
= sizeof(empty_data_content
);
373 msg
->bare_content
= (LPBYTE
)empty_data_content
;
378 typedef struct _CHashEncodeMsg
383 CRYPT_DATA_BLOB data
;
386 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
388 CHashEncodeMsg
*msg
= hCryptMsg
;
390 CryptMemFree(msg
->data
.pbData
);
391 CryptDestroyHash(msg
->hash
);
392 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
393 CryptReleaseContext(msg
->prov
, 0);
396 static BOOL
CRYPT_EncodePKCSDigestedData(CHashEncodeMsg
*msg
, void *pvData
,
401 DWORD size
= sizeof(algID
);
403 ret
= CryptGetHashParam(msg
->hash
, HP_ALGID
, (BYTE
*)&algID
, &size
, 0);
406 CRYPT_DIGESTED_DATA digestedData
= { 0 };
407 char oid_rsa_data
[] = szOID_RSA_data
;
409 digestedData
.version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
410 digestedData
.DigestAlgorithm
.pszObjId
= (LPSTR
)CertAlgIdToOID(algID
);
411 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
412 /* Quirk: OID is only encoded messages if an update has happened */
413 if (msg
->base
.state
!= MsgStateInit
)
414 digestedData
.ContentInfo
.pszObjId
= oid_rsa_data
;
415 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->data
.cbData
)
417 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &msg
->data
,
418 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
419 (LPBYTE
)&digestedData
.ContentInfo
.Content
.pbData
,
420 &digestedData
.ContentInfo
.Content
.cbData
);
422 if (msg
->base
.state
== MsgStateFinalized
)
424 size
= sizeof(DWORD
);
425 ret
= CryptGetHashParam(msg
->hash
, HP_HASHSIZE
,
426 (LPBYTE
)&digestedData
.hash
.cbData
, &size
, 0);
429 digestedData
.hash
.pbData
= CryptMemAlloc(
430 digestedData
.hash
.cbData
);
431 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
,
432 digestedData
.hash
.pbData
, &digestedData
.hash
.cbData
, 0);
436 ret
= CRYPT_AsnEncodePKCSDigestedData(&digestedData
, pvData
,
438 CryptMemFree(digestedData
.hash
.pbData
);
439 LocalFree(digestedData
.ContentInfo
.Content
.pbData
);
444 static BOOL
CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
445 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
447 CHashEncodeMsg
*msg
= hCryptMsg
;
450 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
455 case CMSG_BARE_CONTENT_PARAM
:
456 if (msg
->base
.streamed
)
457 SetLastError(E_INVALIDARG
);
459 ret
= CRYPT_EncodePKCSDigestedData(msg
, pvData
, pcbData
);
461 case CMSG_CONTENT_PARAM
:
463 CRYPT_CONTENT_INFO info
;
465 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
466 &info
.Content
.cbData
);
469 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
470 if (info
.Content
.pbData
)
472 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
473 info
.Content
.pbData
, &info
.Content
.cbData
);
476 char oid_rsa_hashed
[] = szOID_RSA_hashedData
;
478 info
.pszObjId
= oid_rsa_hashed
;
479 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
480 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
482 CryptMemFree(info
.Content
.pbData
);
489 case CMSG_COMPUTED_HASH_PARAM
:
490 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
492 case CMSG_VERSION_PARAM
:
493 if (msg
->base
.state
!= MsgStateFinalized
)
494 SetLastError(CRYPT_E_MSG_ERROR
);
497 DWORD version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
499 /* Since the data are always encoded as octets, the version is
500 * always 0 (see rfc3852, section 7)
502 ret
= CRYPT_CopyParam(pvData
, pcbData
, &version
, sizeof(version
));
506 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
511 static BOOL
CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
512 DWORD cbData
, BOOL fFinal
)
514 CHashEncodeMsg
*msg
= hCryptMsg
;
517 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
519 if (msg
->base
.state
== MsgStateFinalized
)
520 SetLastError(CRYPT_E_MSG_ERROR
);
521 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
523 /* Doesn't do much, as stream output is never called, and you
524 * can't get the content.
526 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
527 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
532 SetLastError(CRYPT_E_MSG_ERROR
);
535 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
538 msg
->data
.pbData
= CryptMemAlloc(cbData
);
539 if (msg
->data
.pbData
)
541 memcpy(msg
->data
.pbData
+ msg
->data
.cbData
, pbData
, cbData
);
542 msg
->data
.cbData
+= cbData
;
547 msg
->base
.state
= MsgStateFinalized
;
553 static HCRYPTMSG
CHashEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
554 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
557 const CMSG_HASHED_ENCODE_INFO
*info
= pvMsgEncodeInfo
;
561 if (info
->cbSize
!= sizeof(CMSG_HASHED_ENCODE_INFO
))
563 SetLastError(E_INVALIDARG
);
566 if (!(algID
= CertOIDToAlgId(info
->HashAlgorithm
.pszObjId
)))
568 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
571 if (info
->hCryptProv
)
572 prov
= info
->hCryptProv
;
575 prov
= CRYPT_GetDefaultProvider();
576 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
578 msg
= CryptMemAlloc(sizeof(CHashEncodeMsg
));
581 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
582 CHashEncodeMsg_Close
, CHashEncodeMsg_GetParam
, CHashEncodeMsg_Update
,
583 CRYPT_DefaultMsgControl
);
585 msg
->data
.cbData
= 0;
586 msg
->data
.pbData
= NULL
;
587 if (!CryptCreateHash(prov
, algID
, 0, 0, &msg
->hash
))
596 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
599 PCERT_INFO pCertInfo
;
600 HCRYPTPROV hCryptProv
;
602 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm
;
605 PCRYPT_ATTRIBUTE rgAuthAttr
;
607 PCRYPT_ATTRIBUTE rgUnauthAttr
;
609 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm
;
610 void *pvHashEncryptionAuxInfo
;
611 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS
;
613 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
617 PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners
;
619 PCERT_BLOB rgCertEncoded
;
621 PCRL_BLOB rgCrlEncoded
;
622 DWORD cAttrCertEncoded
;
623 PCERT_BLOB rgAttrCertEncoded
;
624 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS
;
626 static BOOL
CRYPT_IsValidSigner(const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*signer
)
628 if (signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO
) &&
629 signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
631 SetLastError(E_INVALIDARG
);
634 if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
636 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
638 SetLastError(E_INVALIDARG
);
641 if (!signer
->pCertInfo
->Issuer
.cbData
)
643 SetLastError(E_INVALIDARG
);
647 else if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
649 switch (signer
->SignerId
.dwIdChoice
)
652 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
654 SetLastError(E_INVALIDARG
);
657 if (!signer
->pCertInfo
->Issuer
.cbData
)
659 SetLastError(E_INVALIDARG
);
663 case CERT_ID_ISSUER_SERIAL_NUMBER
:
664 if (!signer
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
)
666 SetLastError(E_INVALIDARG
);
669 if (!signer
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
671 SetLastError(E_INVALIDARG
);
675 case CERT_ID_KEY_IDENTIFIER
:
676 if (!signer
->SignerId
.u
.KeyId
.cbData
)
678 SetLastError(E_INVALIDARG
);
683 SetLastError(E_INVALIDARG
);
685 if (signer
->HashEncryptionAlgorithm
.pszObjId
)
687 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
691 if (!signer
->hCryptProv
)
693 SetLastError(E_INVALIDARG
);
696 if (!CertOIDToAlgId(signer
->HashAlgorithm
.pszObjId
))
698 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
704 static BOOL
CRYPT_ConstructBlob(CRYPT_DATA_BLOB
*out
, const CRYPT_DATA_BLOB
*in
)
708 out
->cbData
= in
->cbData
;
711 out
->pbData
= CryptMemAlloc(out
->cbData
);
713 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
722 static BOOL
CRYPT_ConstructBlobArray(DWORD
*outCBlobs
,
723 PCRYPT_DATA_BLOB
*outPBlobs
, DWORD cBlobs
, const CRYPT_DATA_BLOB
*pBlobs
)
730 *outPBlobs
= CryptMemAlloc(cBlobs
* sizeof(CRYPT_DATA_BLOB
));
735 memset(*outPBlobs
, 0, cBlobs
* sizeof(CRYPT_DATA_BLOB
));
736 for (i
= 0; ret
&& i
< cBlobs
; i
++)
737 ret
= CRYPT_ConstructBlob(&(*outPBlobs
)[i
], &pBlobs
[i
]);
745 static void CRYPT_FreeBlobArray(DWORD cBlobs
, PCRYPT_DATA_BLOB blobs
)
749 for (i
= 0; i
< cBlobs
; i
++)
750 CryptMemFree(blobs
[i
].pbData
);
754 static BOOL
CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE
*out
,
755 const CRYPT_ATTRIBUTE
*in
)
759 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
762 strcpy(out
->pszObjId
, in
->pszObjId
);
763 ret
= CRYPT_ConstructBlobArray(&out
->cValue
, &out
->rgValue
,
764 in
->cValue
, in
->rgValue
);
771 static BOOL
CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES
*out
,
772 const CRYPT_ATTRIBUTES
*in
)
776 out
->cAttr
= in
->cAttr
;
779 out
->rgAttr
= CryptMemAlloc(out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
784 memset(out
->rgAttr
, 0, out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
785 for (i
= 0; ret
&& i
< out
->cAttr
; i
++)
786 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[i
], &in
->rgAttr
[i
]);
796 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
797 static BOOL
CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO
*info
,
798 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*in
)
802 if (in
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
804 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
805 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
806 &in
->pCertInfo
->Issuer
);
808 ret
= CRYPT_ConstructBlob(
809 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
810 &in
->pCertInfo
->SerialNumber
);
811 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
812 info
->HashEncryptionAlgorithm
.pszObjId
=
813 in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
;
815 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
816 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.Parameters
);
820 const CRYPT_ALGORITHM_IDENTIFIER
*pEncrAlg
;
822 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS).
823 * See CRYPT_IsValidSigner.
825 if (!in
->SignerId
.dwIdChoice
)
827 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
828 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
829 &in
->pCertInfo
->Issuer
);
831 ret
= CRYPT_ConstructBlob(
832 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
833 &in
->pCertInfo
->SerialNumber
);
834 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
836 else if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
838 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
839 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
840 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
841 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
);
843 ret
= CRYPT_ConstructBlob(
844 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
845 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
);
849 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */
850 info
->dwVersion
= CMSG_SIGNER_INFO_V3
;
851 info
->SignerId
.dwIdChoice
= CERT_ID_KEY_IDENTIFIER
;
852 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.KeyId
,
853 &in
->SignerId
.u
.KeyId
);
855 pEncrAlg
= in
->HashEncryptionAlgorithm
.pszObjId
?
856 &in
->HashEncryptionAlgorithm
:
857 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
;
858 info
->HashEncryptionAlgorithm
.pszObjId
= pEncrAlg
->pszObjId
;
860 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
861 &pEncrAlg
->Parameters
);
863 /* Assumption: algorithm IDs will point to static strings, not
864 * stack-based ones, so copying the pointer values is safe.
866 info
->HashAlgorithm
.pszObjId
= in
->HashAlgorithm
.pszObjId
;
868 ret
= CRYPT_ConstructBlob(&info
->HashAlgorithm
.Parameters
,
869 &in
->HashAlgorithm
.Parameters
);
871 ret
= CRYPT_ConstructAttributes(&info
->AuthAttrs
,
872 (CRYPT_ATTRIBUTES
*)&in
->cAuthAttr
);
874 ret
= CRYPT_ConstructAttributes(&info
->UnauthAttrs
,
875 (CRYPT_ATTRIBUTES
*)&in
->cUnauthAttr
);
879 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO
*info
)
883 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
885 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
886 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
889 CryptMemFree(info
->SignerId
.u
.KeyId
.pbData
);
890 CryptMemFree(info
->HashAlgorithm
.Parameters
.pbData
);
891 CryptMemFree(info
->HashEncryptionAlgorithm
.Parameters
.pbData
);
892 CryptMemFree(info
->EncryptedHash
.pbData
);
893 for (i
= 0; i
< info
->AuthAttrs
.cAttr
; i
++)
895 for (j
= 0; j
< info
->AuthAttrs
.rgAttr
[i
].cValue
; j
++)
896 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
897 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
);
898 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].pszObjId
);
900 CryptMemFree(info
->AuthAttrs
.rgAttr
);
901 for (i
= 0; i
< info
->UnauthAttrs
.cAttr
; i
++)
903 for (j
= 0; j
< info
->UnauthAttrs
.rgAttr
[i
].cValue
; j
++)
904 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
905 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
);
906 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].pszObjId
);
908 CryptMemFree(info
->UnauthAttrs
.rgAttr
);
911 typedef struct _CSignerHandles
913 HCRYPTHASH contentHash
;
914 HCRYPTHASH authAttrHash
;
917 typedef struct _CSignedMsgData
919 CRYPT_SIGNED_INFO
*info
;
921 CSignerHandles
*signerHandles
;
924 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
925 * Assumes signerIndex is a valid idnex, and that msg_data's info has already
928 static BOOL
CSignedMsgData_ConstructSignerHandles(CSignedMsgData
*msg_data
,
929 DWORD signerIndex
, HCRYPTPROV crypt_prov
)
934 algID
= CertOIDToAlgId(
935 msg_data
->info
->rgSignerInfo
[signerIndex
].HashAlgorithm
.pszObjId
);
936 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
937 &msg_data
->signerHandles
->contentHash
);
938 if (ret
&& msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
> 0)
939 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
940 &msg_data
->signerHandles
->authAttrHash
);
944 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
947 static BOOL
CSignedMsgData_AllocateHandles(CSignedMsgData
*msg_data
)
951 if (msg_data
->info
->cSignerInfo
)
953 msg_data
->signerHandles
=
954 CryptMemAlloc(msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
955 if (msg_data
->signerHandles
)
957 msg_data
->cSignerHandle
= msg_data
->info
->cSignerInfo
;
958 memset(msg_data
->signerHandles
, 0,
959 msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
963 msg_data
->cSignerHandle
= 0;
969 msg_data
->cSignerHandle
= 0;
970 msg_data
->signerHandles
= NULL
;
975 static void CSignedMsgData_CloseHandles(CSignedMsgData
*msg_data
)
979 for (i
= 0; i
< msg_data
->cSignerHandle
; i
++)
981 if (msg_data
->signerHandles
[i
].contentHash
)
982 CryptDestroyHash(msg_data
->signerHandles
[i
].contentHash
);
983 if (msg_data
->signerHandles
[i
].authAttrHash
)
984 CryptDestroyHash(msg_data
->signerHandles
[i
].authAttrHash
);
986 CryptMemFree(msg_data
->signerHandles
);
987 msg_data
->signerHandles
= NULL
;
988 msg_data
->cSignerHandle
= 0;
991 static BOOL
CSignedMsgData_UpdateHash(CSignedMsgData
*msg_data
,
992 const BYTE
*pbData
, DWORD cbData
)
997 for (i
= 0; ret
&& i
< msg_data
->cSignerHandle
; i
++)
998 ret
= CryptHashData(msg_data
->signerHandles
[i
].contentHash
, pbData
,
1003 static BOOL
CRYPT_AppendAttribute(CRYPT_ATTRIBUTES
*out
,
1004 const CRYPT_ATTRIBUTE
*in
)
1008 out
->rgAttr
= CryptMemRealloc(out
->rgAttr
,
1009 (out
->cAttr
+ 1) * sizeof(CRYPT_ATTRIBUTE
));
1012 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[out
->cAttr
], in
);
1019 static BOOL
CSignedMsgData_AppendMessageDigestAttribute(
1020 CSignedMsgData
*msg_data
, DWORD signerIndex
)
1024 CRYPT_HASH_BLOB hash
= { 0, NULL
}, encodedHash
= { 0, NULL
};
1025 char messageDigest
[] = szOID_RSA_messageDigest
;
1026 CRYPT_ATTRIBUTE messageDigestAttr
= { messageDigest
, 1, &encodedHash
};
1028 size
= sizeof(DWORD
);
1029 ret
= CryptGetHashParam(
1030 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHSIZE
,
1031 (LPBYTE
)&hash
.cbData
, &size
, 0);
1034 hash
.pbData
= CryptMemAlloc(hash
.cbData
);
1035 ret
= CryptGetHashParam(
1036 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHVAL
,
1037 hash
.pbData
, &hash
.cbData
, 0);
1040 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &hash
, CRYPT_ENCODE_ALLOC_FLAG
,
1041 NULL
, (LPBYTE
)&encodedHash
.pbData
, &encodedHash
.cbData
);
1044 ret
= CRYPT_AppendAttribute(
1045 &msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
,
1046 &messageDigestAttr
);
1047 LocalFree(encodedHash
.pbData
);
1050 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
++)
1134 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1135 hash
= msg_data
->signerHandles
[i
].authAttrHash
;
1137 hash
= msg_data
->signerHandles
[i
].contentHash
;
1138 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0, NULL
,
1139 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1142 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
=
1144 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1145 if (msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
)
1147 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0,
1148 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
,
1149 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1152 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
);
1161 static BOOL
CSignedMsgData_Update(CSignedMsgData
*msg_data
,
1162 const BYTE
*pbData
, DWORD cbData
, BOOL fFinal
, SignOrVerify flag
)
1164 BOOL ret
= CSignedMsgData_UpdateHash(msg_data
, pbData
, cbData
);
1168 ret
= CSignedMsgData_UpdateAuthenticatedAttributes(msg_data
, flag
);
1169 if (ret
&& flag
== Sign
)
1170 ret
= CSignedMsgData_Sign(msg_data
);
1175 typedef struct _CSignedEncodeMsg
1179 CRYPT_DATA_BLOB data
;
1180 CSignedMsgData msg_data
;
1183 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1185 CSignedEncodeMsg
*msg
= hCryptMsg
;
1188 CryptMemFree(msg
->innerOID
);
1189 CryptMemFree(msg
->data
.pbData
);
1190 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCertEncoded
,
1191 msg
->msg_data
.info
->rgCertEncoded
);
1192 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCrlEncoded
,
1193 msg
->msg_data
.info
->rgCrlEncoded
);
1194 for (i
= 0; i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1195 CSignerInfo_Free(&msg
->msg_data
.info
->rgSignerInfo
[i
]);
1196 CSignedMsgData_CloseHandles(&msg
->msg_data
);
1197 CryptMemFree(msg
->msg_data
.info
->rgSignerInfo
);
1198 CryptMemFree(msg
->msg_data
.info
);
1201 static BOOL
CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1202 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1204 CSignedEncodeMsg
*msg
= hCryptMsg
;
1207 switch (dwParamType
)
1209 case CMSG_CONTENT_PARAM
:
1211 CRYPT_CONTENT_INFO info
;
1213 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1214 &info
.Content
.cbData
);
1217 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1218 if (info
.Content
.pbData
)
1220 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1221 info
.Content
.pbData
, &info
.Content
.cbData
);
1224 char oid_rsa_signed
[] = szOID_RSA_signedData
;
1226 info
.pszObjId
= oid_rsa_signed
;
1227 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1228 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1230 CryptMemFree(info
.Content
.pbData
);
1237 case CMSG_BARE_CONTENT_PARAM
:
1239 CRYPT_SIGNED_INFO info
;
1240 BOOL freeContent
= FALSE
;
1242 info
= *msg
->msg_data
.info
;
1243 if (!msg
->innerOID
|| !strcmp(msg
->innerOID
, szOID_RSA_data
))
1245 char oid_rsa_data
[] = szOID_RSA_data
;
1247 /* Quirk: OID is only encoded messages if an update has happened */
1248 if (msg
->base
.state
!= MsgStateInit
)
1249 info
.content
.pszObjId
= oid_rsa_data
;
1251 info
.content
.pszObjId
= NULL
;
1252 if (msg
->data
.cbData
)
1254 CRYPT_DATA_BLOB blob
= { msg
->data
.cbData
, msg
->data
.pbData
};
1256 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1257 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
1258 &info
.content
.Content
.pbData
, &info
.content
.Content
.cbData
);
1263 info
.content
.Content
.cbData
= 0;
1264 info
.content
.Content
.pbData
= NULL
;
1270 info
.content
.pszObjId
= msg
->innerOID
;
1271 info
.content
.Content
.cbData
= msg
->data
.cbData
;
1272 info
.content
.Content
.pbData
= msg
->data
.pbData
;
1277 ret
= CRYPT_AsnEncodeCMSSignedInfo(&info
, pvData
, pcbData
);
1279 LocalFree(info
.content
.Content
.pbData
);
1283 case CMSG_COMPUTED_HASH_PARAM
:
1284 if (dwIndex
>= msg
->msg_data
.cSignerHandle
)
1285 SetLastError(CRYPT_E_INVALID_INDEX
);
1287 ret
= CryptGetHashParam(
1288 msg
->msg_data
.signerHandles
[dwIndex
].contentHash
, HP_HASHVAL
,
1289 pvData
, pcbData
, 0);
1291 case CMSG_ENCODED_SIGNER
:
1292 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1293 SetLastError(CRYPT_E_INVALID_INDEX
);
1295 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1296 CMS_SIGNER_INFO
, &msg
->msg_data
.info
->rgSignerInfo
[dwIndex
], 0,
1297 NULL
, pvData
, pcbData
);
1299 case CMSG_VERSION_PARAM
:
1300 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->msg_data
.info
->version
,
1301 sizeof(msg
->msg_data
.info
->version
));
1304 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1309 static BOOL
CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1310 DWORD cbData
, BOOL fFinal
)
1312 CSignedEncodeMsg
*msg
= hCryptMsg
;
1315 if (msg
->base
.state
== MsgStateFinalized
)
1316 SetLastError(CRYPT_E_MSG_ERROR
);
1317 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1319 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
, fFinal
,
1321 if (msg
->base
.streamed
)
1322 FIXME("streamed partial stub\n");
1323 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1328 SetLastError(CRYPT_E_MSG_ERROR
);
1333 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1334 if (msg
->data
.pbData
)
1336 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1337 msg
->data
.cbData
= cbData
;
1344 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
,
1346 msg
->base
.state
= MsgStateFinalized
;
1352 static HCRYPTMSG
CSignedEncodeMsg_Open(DWORD dwFlags
,
1353 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1354 PCMSG_STREAM_INFO pStreamInfo
)
1356 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1358 CSignedEncodeMsg
*msg
;
1360 if (info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO
) &&
1361 info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1363 SetLastError(E_INVALIDARG
);
1366 if (info
->cbSize
== sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
) &&
1367 info
->cAttrCertEncoded
)
1369 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1372 for (i
= 0; i
< info
->cSigners
; i
++)
1373 if (!CRYPT_IsValidSigner(&info
->rgSigners
[i
]))
1375 msg
= CryptMemAlloc(sizeof(CSignedEncodeMsg
));
1380 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1381 CSignedEncodeMsg_Close
, CSignedEncodeMsg_GetParam
,
1382 CSignedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1383 if (pszInnerContentObjID
)
1385 msg
->innerOID
= CryptMemAlloc(strlen(pszInnerContentObjID
) + 1);
1387 strcpy(msg
->innerOID
, pszInnerContentObjID
);
1392 msg
->innerOID
= NULL
;
1393 msg
->data
.cbData
= 0;
1394 msg
->data
.pbData
= NULL
;
1396 msg
->msg_data
.info
= CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO
));
1398 msg
->msg_data
.info
= NULL
;
1399 if (msg
->msg_data
.info
)
1401 memset(msg
->msg_data
.info
, 0, sizeof(CRYPT_SIGNED_INFO
));
1402 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V1
;
1410 msg
->msg_data
.info
->rgSignerInfo
=
1411 CryptMemAlloc(info
->cSigners
* sizeof(CMSG_CMS_SIGNER_INFO
));
1412 if (msg
->msg_data
.info
->rgSignerInfo
)
1414 msg
->msg_data
.info
->cSignerInfo
= info
->cSigners
;
1415 memset(msg
->msg_data
.info
->rgSignerInfo
, 0,
1416 msg
->msg_data
.info
->cSignerInfo
*
1417 sizeof(CMSG_CMS_SIGNER_INFO
));
1418 ret
= CSignedMsgData_AllocateHandles(&msg
->msg_data
);
1419 for (i
= 0; ret
&& i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1421 if (info
->rgSigners
[i
].SignerId
.dwIdChoice
==
1422 CERT_ID_KEY_IDENTIFIER
)
1423 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V3
;
1424 ret
= CSignerInfo_Construct(
1425 &msg
->msg_data
.info
->rgSignerInfo
[i
],
1426 &info
->rgSigners
[i
]);
1429 ret
= CSignedMsgData_ConstructSignerHandles(
1430 &msg
->msg_data
, i
, info
->rgSigners
[i
].hCryptProv
);
1431 if (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1432 CryptReleaseContext(info
->rgSigners
[i
].hCryptProv
,
1442 msg
->msg_data
.info
->cSignerInfo
= 0;
1443 msg
->msg_data
.signerHandles
= NULL
;
1444 msg
->msg_data
.cSignerHandle
= 0;
1448 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCertEncoded
,
1449 &msg
->msg_data
.info
->rgCertEncoded
, info
->cCertEncoded
,
1450 info
->rgCertEncoded
);
1452 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCrlEncoded
,
1453 &msg
->msg_data
.info
->rgCrlEncoded
, info
->cCrlEncoded
,
1454 info
->rgCrlEncoded
);
1457 CSignedEncodeMsg_Close(msg
);
1464 typedef struct _CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
1467 HCRYPTPROV_LEGACY hCryptProv
;
1468 CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm
;
1469 void *pvEncryptionAuxInfo
;
1471 PCERT_INFO
*rgpRecipientCert
;
1472 PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients
;
1474 PCERT_BLOB rgCertEncoded
;
1476 PCRL_BLOB rgCrlEncoded
;
1477 DWORD cAttrCertEncoded
;
1478 PCERT_BLOB rgAttrCertEncoded
;
1479 DWORD cUnprotectedAttr
;
1480 PCRYPT_ATTRIBUTE rgUnprotectedAttr
;
1481 } CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
, *PCMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
;
1483 typedef struct _CEnvelopedEncodeMsg
1486 CRYPT_ALGORITHM_IDENTIFIER algo
;
1489 DWORD cRecipientInfo
;
1490 CMSG_KEY_TRANS_RECIPIENT_INFO
*recipientInfo
;
1491 CRYPT_DATA_BLOB data
;
1492 } CEnvelopedEncodeMsg
;
1494 static BOOL
CRYPT_ConstructAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
1495 const CRYPT_ALGORITHM_IDENTIFIER
*in
)
1497 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
1500 strcpy(out
->pszObjId
, in
->pszObjId
);
1501 return CRYPT_ConstructBlob(&out
->Parameters
, &in
->Parameters
);
1507 static BOOL
CRYPT_ConstructBitBlob(CRYPT_BIT_BLOB
*out
, const CRYPT_BIT_BLOB
*in
)
1509 out
->cbData
= in
->cbData
;
1510 out
->cUnusedBits
= in
->cUnusedBits
;
1513 out
->pbData
= CryptMemAlloc(out
->cbData
);
1515 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
1524 static BOOL
CRYPT_GenKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, ALG_ID algID
)
1526 static HCRYPTOIDFUNCSET set
= NULL
;
1527 PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY genKeyFunc
= NULL
;
1528 HCRYPTOIDFUNCADDR hFunc
;
1532 set
= CryptInitOIDFunctionSet(CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC
, 0);
1533 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1534 info
->ContentEncryptionAlgorithm
.pszObjId
, 0, (void **)&genKeyFunc
, &hFunc
);
1537 ret
= genKeyFunc(info
, 0, NULL
);
1538 CryptFreeOIDFunctionAddress(hFunc
, 0);
1541 ret
= CryptGenKey(info
->hCryptProv
, algID
, CRYPT_EXPORTABLE
,
1542 &info
->hContentEncryptKey
);
1546 static BOOL WINAPI
CRYPT_ExportKeyTrans(
1547 PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo
,
1548 PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo
,
1549 PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo
,
1550 DWORD dwFlags
, void *pvReserved
)
1552 CERT_PUBLIC_KEY_INFO keyInfo
;
1556 ret
= CRYPT_ConstructAlgorithmId(&keyInfo
.Algorithm
,
1557 &pKeyTransEncodeInfo
->KeyEncryptionAlgorithm
);
1559 CRYPT_ConstructBitBlob(&keyInfo
.PublicKey
,
1560 &pKeyTransEncodeInfo
->RecipientPublicKey
);
1563 ret
= CryptImportPublicKeyInfo(pKeyTransEncodeInfo
->hCryptProv
,
1564 X509_ASN_ENCODING
, &keyInfo
, &expKey
);
1570 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
, expKey
,
1571 SIMPLEBLOB
, 0, NULL
, &size
);
1572 keyBlob
= CryptMemAlloc(size
);
1575 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
,
1576 expKey
, SIMPLEBLOB
, 0, keyBlob
, &size
);
1579 DWORD head
= sizeof(BLOBHEADER
) + sizeof(ALG_ID
);
1581 pKeyTransEncryptInfo
->EncryptedKey
.pbData
=
1582 CryptMemAlloc(size
- head
);
1583 if (pKeyTransEncryptInfo
->EncryptedKey
.pbData
)
1587 pKeyTransEncryptInfo
->EncryptedKey
.cbData
= size
- head
;
1588 for (i
= size
- 1; i
>= head
; --i
, ++k
)
1589 pKeyTransEncryptInfo
->EncryptedKey
.pbData
[k
] =
1595 CryptMemFree(keyBlob
);
1599 CryptDestroyKey(expKey
);
1602 CryptMemFree(keyInfo
.Algorithm
.pszObjId
);
1603 CryptMemFree(keyInfo
.Algorithm
.Parameters
.pbData
);
1607 static BOOL
CRYPT_ExportEncryptedKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, DWORD i
,
1608 CRYPT_DATA_BLOB
*key
)
1610 static HCRYPTOIDFUNCSET set
= NULL
;
1611 PFN_CMSG_EXPORT_KEY_TRANS exportKeyFunc
= NULL
;
1612 HCRYPTOIDFUNCADDR hFunc
= NULL
;
1613 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1614 info
->rgCmsRecipients
[i
].u
.pKeyTrans
;
1615 CMSG_KEY_TRANS_ENCRYPT_INFO encryptInfo
;
1618 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
1619 encryptInfo
.cbSize
= sizeof(encryptInfo
);
1620 encryptInfo
.dwRecipientIndex
= i
;
1621 ret
= CRYPT_ConstructAlgorithmId(&encryptInfo
.KeyEncryptionAlgorithm
,
1622 &encodeInfo
->KeyEncryptionAlgorithm
);
1625 set
= CryptInitOIDFunctionSet(CMSG_OID_EXPORT_KEY_TRANS_FUNC
, 0);
1626 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1627 encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
, 0, (void **)&exportKeyFunc
,
1630 exportKeyFunc
= CRYPT_ExportKeyTrans
;
1633 ret
= exportKeyFunc(info
, encodeInfo
, &encryptInfo
, 0, NULL
);
1636 key
->cbData
= encryptInfo
.EncryptedKey
.cbData
;
1637 key
->pbData
= encryptInfo
.EncryptedKey
.pbData
;
1641 CryptFreeOIDFunctionAddress(hFunc
, 0);
1643 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
);
1644 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.Parameters
.pbData
);
1648 static BOOL
CContentEncryptInfo_Construct(CMSG_CONTENT_ENCRYPT_INFO
*info
,
1649 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*in
, HCRYPTPROV prov
)
1653 info
->cbSize
= sizeof(CMSG_CONTENT_ENCRYPT_INFO
);
1654 info
->hCryptProv
= prov
;
1655 ret
= CRYPT_ConstructAlgorithmId(&info
->ContentEncryptionAlgorithm
,
1656 &in
->ContentEncryptionAlgorithm
);
1657 info
->pvEncryptionAuxInfo
= in
->pvEncryptionAuxInfo
;
1658 info
->cRecipients
= in
->cRecipients
;
1661 info
->rgCmsRecipients
= CryptMemAlloc(in
->cRecipients
*
1662 sizeof(CMSG_RECIPIENT_ENCODE_INFO
));
1663 if (info
->rgCmsRecipients
)
1667 for (i
= 0; ret
&& i
< in
->cRecipients
; ++i
)
1669 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
;
1670 CERT_INFO
*cert
= in
->rgpRecipientCert
[i
];
1672 info
->rgCmsRecipients
[i
].dwRecipientChoice
=
1673 CMSG_KEY_TRANS_RECIPIENT
;
1674 encodeInfo
= CryptMemAlloc(sizeof(*encodeInfo
));
1675 info
->rgCmsRecipients
[i
].u
.pKeyTrans
= encodeInfo
;
1678 encodeInfo
->cbSize
= sizeof(*encodeInfo
);
1679 ret
= CRYPT_ConstructAlgorithmId(
1680 &encodeInfo
->KeyEncryptionAlgorithm
,
1681 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1682 encodeInfo
->pvKeyEncryptionAuxInfo
= NULL
;
1683 encodeInfo
->hCryptProv
= prov
;
1685 ret
= CRYPT_ConstructBitBlob(
1686 &encodeInfo
->RecipientPublicKey
,
1687 &cert
->SubjectPublicKeyInfo
.PublicKey
);
1689 ret
= CRYPT_ConstructBlob(
1690 &encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.Issuer
,
1693 ret
= CRYPT_ConstructBlob(
1694 &encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
,
1695 &cert
->SerialNumber
);
1704 info
->pfnAlloc
= CryptMemAlloc
;
1705 info
->pfnFree
= CryptMemFree
;
1709 static void CContentEncryptInfo_Free(CMSG_CONTENT_ENCRYPT_INFO
*info
)
1711 CryptMemFree(info
->ContentEncryptionAlgorithm
.pszObjId
);
1712 CryptMemFree(info
->ContentEncryptionAlgorithm
.Parameters
.pbData
);
1713 if (info
->rgCmsRecipients
)
1717 for (i
= 0; i
< info
->cRecipients
; ++i
)
1719 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1720 info
->rgCmsRecipients
[i
].u
.pKeyTrans
;
1722 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.pszObjId
);
1723 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1724 CryptMemFree(encodeInfo
->RecipientPublicKey
.pbData
);
1726 encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
1728 encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
1729 CryptMemFree(encodeInfo
);
1731 CryptMemFree(info
->rgCmsRecipients
);
1735 static BOOL
CRecipientInfo_Construct(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
,
1736 const CERT_INFO
*cert
, CRYPT_DATA_BLOB
*key
)
1740 info
->dwVersion
= CMSG_KEY_TRANS_PKCS_1_5_VERSION
;
1741 info
->RecipientId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
1742 ret
= CRYPT_ConstructBlob(&info
->RecipientId
.u
.IssuerSerialNumber
.Issuer
,
1745 ret
= CRYPT_ConstructBlob(
1746 &info
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
,
1747 &cert
->SerialNumber
);
1749 ret
= CRYPT_ConstructAlgorithmId(&info
->KeyEncryptionAlgorithm
,
1750 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1751 info
->EncryptedKey
.cbData
= key
->cbData
;
1752 info
->EncryptedKey
.pbData
= key
->pbData
;
1756 static void CRecipientInfo_Free(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
)
1758 CryptMemFree(info
->RecipientId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
1759 CryptMemFree(info
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
1760 CryptMemFree(info
->KeyEncryptionAlgorithm
.pszObjId
);
1761 CryptMemFree(info
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1762 CryptMemFree(info
->EncryptedKey
.pbData
);
1765 static void CEnvelopedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1767 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1769 CryptMemFree(msg
->algo
.pszObjId
);
1770 CryptMemFree(msg
->algo
.Parameters
.pbData
);
1771 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1772 CryptReleaseContext(msg
->prov
, 0);
1773 CryptDestroyKey(msg
->key
);
1774 if (msg
->recipientInfo
)
1778 for (i
= 0; i
< msg
->cRecipientInfo
; ++i
)
1779 CRecipientInfo_Free(&msg
->recipientInfo
[i
]);
1780 CryptMemFree(msg
->recipientInfo
);
1782 CryptMemFree(msg
->data
.pbData
);
1785 static BOOL
CEnvelopedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1786 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1788 FIXME("(%p, %d, %d, %p, %p): stub\n", hCryptMsg
, dwParamType
, dwIndex
,
1793 static BOOL
CEnvelopedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1794 DWORD cbData
, BOOL fFinal
)
1796 FIXME("(%p, %p, %d, %d): stub\n", hCryptMsg
, pbData
, cbData
, fFinal
);
1800 static HCRYPTMSG
CEnvelopedEncodeMsg_Open(DWORD dwFlags
,
1801 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1802 PCMSG_STREAM_INFO pStreamInfo
)
1804 CEnvelopedEncodeMsg
*msg
;
1805 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1809 if (info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO
) &&
1810 info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1812 SetLastError(E_INVALIDARG
);
1815 if (info
->cbSize
== sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1816 FIXME("CMS fields unsupported\n");
1817 if (!(algID
= CertOIDToAlgId(info
->ContentEncryptionAlgorithm
.pszObjId
)))
1819 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
1822 if (info
->cRecipients
&& !info
->rgpRecipientCert
)
1824 SetLastError(E_INVALIDARG
);
1827 if (info
->hCryptProv
)
1828 prov
= info
->hCryptProv
;
1831 prov
= CRYPT_GetDefaultProvider();
1832 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
1834 msg
= CryptMemAlloc(sizeof(CEnvelopedEncodeMsg
));
1837 CRYPT_DATA_BLOB encryptedKey
= { 0, NULL
};
1838 CMSG_CONTENT_ENCRYPT_INFO encryptInfo
;
1842 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1843 CEnvelopedEncodeMsg_Close
, CEnvelopedEncodeMsg_GetParam
,
1844 CEnvelopedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1845 ret
= CRYPT_ConstructAlgorithmId(&msg
->algo
,
1846 &info
->ContentEncryptionAlgorithm
);
1848 msg
->data
.cbData
= 0;
1849 msg
->data
.pbData
= NULL
;
1850 msg
->cRecipientInfo
= info
->cRecipients
;
1851 msg
->recipientInfo
= CryptMemAlloc(info
->cRecipients
*
1852 sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
));
1853 if (!msg
->recipientInfo
)
1855 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
1858 ret
= CContentEncryptInfo_Construct(&encryptInfo
, info
, prov
);
1861 ret
= CRYPT_GenKey(&encryptInfo
, algID
);
1863 msg
->key
= encryptInfo
.hContentEncryptKey
;
1866 for (i
= 0; ret
&& i
< msg
->cRecipientInfo
; ++i
)
1868 ret
= CRYPT_ExportEncryptedKey(&encryptInfo
, i
, &encryptedKey
);
1870 ret
= CRecipientInfo_Construct(&msg
->recipientInfo
[i
],
1871 info
->rgpRecipientCert
[i
], &encryptedKey
);
1873 CContentEncryptInfo_Free(&encryptInfo
);
1880 if (!msg
&& (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
))
1881 CryptReleaseContext(prov
, 0);
1885 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
1886 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
1887 PCMSG_STREAM_INFO pStreamInfo
)
1889 HCRYPTMSG msg
= NULL
;
1891 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
1892 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
1894 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
1896 SetLastError(E_INVALIDARG
);
1902 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1903 pszInnerContentObjID
, pStreamInfo
);
1906 msg
= CHashEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1907 pszInnerContentObjID
, pStreamInfo
);
1910 msg
= CSignedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1911 pszInnerContentObjID
, pStreamInfo
);
1913 case CMSG_ENVELOPED
:
1914 msg
= CEnvelopedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
1915 pszInnerContentObjID
, pStreamInfo
);
1917 case CMSG_SIGNED_AND_ENVELOPED
:
1918 case CMSG_ENCRYPTED
:
1919 /* defined but invalid, fall through */
1921 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1926 typedef struct _CDecodeMsg
1930 HCRYPTPROV crypt_prov
;
1933 CSignedMsgData signed_data
;
1935 CRYPT_DATA_BLOB msg_data
;
1936 CRYPT_DATA_BLOB detached_data
;
1937 PCONTEXT_PROPERTY_LIST properties
;
1940 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg
)
1942 CDecodeMsg
*msg
= hCryptMsg
;
1944 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1945 CryptReleaseContext(msg
->crypt_prov
, 0);
1950 CryptDestroyHash(msg
->u
.hash
);
1953 if (msg
->u
.signed_data
.info
)
1955 LocalFree(msg
->u
.signed_data
.info
);
1956 CSignedMsgData_CloseHandles(&msg
->u
.signed_data
);
1960 CryptMemFree(msg
->msg_data
.pbData
);
1961 CryptMemFree(msg
->detached_data
.pbData
);
1962 ContextPropertyList_Free(msg
->properties
);
1965 static BOOL
CDecodeMsg_CopyData(CRYPT_DATA_BLOB
*blob
, const BYTE
*pbData
,
1973 blob
->pbData
= CryptMemRealloc(blob
->pbData
,
1974 blob
->cbData
+ cbData
);
1976 blob
->pbData
= CryptMemAlloc(cbData
);
1979 memcpy(blob
->pbData
+ blob
->cbData
, pbData
, cbData
);
1980 blob
->cbData
+= cbData
;
1988 static BOOL
CDecodeMsg_DecodeDataContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
)
1991 CRYPT_DATA_BLOB
*data
;
1994 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1995 blob
->pbData
, blob
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &data
, &size
);
1998 ret
= ContextPropertyList_SetProperty(msg
->properties
,
1999 CMSG_CONTENT_PARAM
, data
->pbData
, data
->cbData
);
2005 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg
*msg
, DWORD param
,
2006 const CRYPT_ALGORITHM_IDENTIFIER
*id
)
2008 static const BYTE nullParams
[] = { ASN_NULL
, 0 };
2009 CRYPT_ALGORITHM_IDENTIFIER
*copy
;
2010 DWORD len
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
2012 /* Linearize algorithm id */
2013 len
+= strlen(id
->pszObjId
) + 1;
2014 len
+= id
->Parameters
.cbData
;
2015 copy
= CryptMemAlloc(len
);
2019 (LPSTR
)((BYTE
*)copy
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2020 strcpy(copy
->pszObjId
, id
->pszObjId
);
2021 copy
->Parameters
.pbData
= (BYTE
*)copy
->pszObjId
+ strlen(id
->pszObjId
)
2023 /* Trick: omit NULL parameters */
2024 if (id
->Parameters
.cbData
== sizeof(nullParams
) &&
2025 !memcmp(id
->Parameters
.pbData
, nullParams
, sizeof(nullParams
)))
2027 copy
->Parameters
.cbData
= 0;
2028 len
-= sizeof(nullParams
);
2031 copy
->Parameters
.cbData
= id
->Parameters
.cbData
;
2032 if (copy
->Parameters
.cbData
)
2033 memcpy(copy
->Parameters
.pbData
, id
->Parameters
.pbData
,
2034 id
->Parameters
.cbData
);
2035 ContextPropertyList_SetProperty(msg
->properties
, param
, (BYTE
*)copy
,
2041 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER
*id
)
2043 id
->pszObjId
= (LPSTR
)((BYTE
*)id
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2044 id
->Parameters
.pbData
= (BYTE
*)id
->pszObjId
+ strlen(id
->pszObjId
) + 1;
2047 static BOOL
CDecodeMsg_DecodeHashedContent(CDecodeMsg
*msg
,
2048 const CRYPT_DER_BLOB
*blob
)
2051 CRYPT_DIGESTED_DATA
*digestedData
;
2054 ret
= CRYPT_AsnDecodePKCSDigestedData(blob
->pbData
, blob
->cbData
,
2055 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_DIGESTED_DATA
*)&digestedData
,
2059 ContextPropertyList_SetProperty(msg
->properties
, CMSG_VERSION_PARAM
,
2060 (const BYTE
*)&digestedData
->version
, sizeof(digestedData
->version
));
2061 CDecodeMsg_SaveAlgorithmID(msg
, CMSG_HASH_ALGORITHM_PARAM
,
2062 &digestedData
->DigestAlgorithm
);
2063 ContextPropertyList_SetProperty(msg
->properties
,
2064 CMSG_INNER_CONTENT_TYPE_PARAM
,
2065 (const BYTE
*)digestedData
->ContentInfo
.pszObjId
,
2066 digestedData
->ContentInfo
.pszObjId
?
2067 strlen(digestedData
->ContentInfo
.pszObjId
) + 1 : 0);
2068 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
2070 if (digestedData
->ContentInfo
.Content
.cbData
)
2071 CDecodeMsg_DecodeDataContent(msg
,
2072 &digestedData
->ContentInfo
.Content
);
2074 ContextPropertyList_SetProperty(msg
->properties
,
2075 CMSG_CONTENT_PARAM
, NULL
, 0);
2077 ContextPropertyList_SetProperty(msg
->properties
, CMSG_HASH_DATA_PARAM
,
2078 digestedData
->hash
.pbData
, digestedData
->hash
.cbData
);
2079 LocalFree(digestedData
);
2084 static BOOL
CDecodeMsg_DecodeSignedContent(CDecodeMsg
*msg
,
2085 const CRYPT_DER_BLOB
*blob
)
2088 CRYPT_SIGNED_INFO
*signedInfo
;
2091 ret
= CRYPT_AsnDecodeCMSSignedInfo(blob
->pbData
, blob
->cbData
,
2092 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_SIGNED_INFO
*)&signedInfo
,
2095 msg
->u
.signed_data
.info
= signedInfo
;
2099 /* Decodes the content in blob as the type given, and updates the value
2100 * (type, parameters, etc.) of msg based on what blob contains.
2101 * It doesn't just use msg's type, to allow a recursive call from an implicitly
2102 * typed message once the outer content info has been decoded.
2104 static BOOL
CDecodeMsg_DecodeContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
,
2112 if ((ret
= CDecodeMsg_DecodeDataContent(msg
, blob
)))
2113 msg
->type
= CMSG_DATA
;
2116 if ((ret
= CDecodeMsg_DecodeHashedContent(msg
, blob
)))
2117 msg
->type
= CMSG_HASHED
;
2119 case CMSG_ENVELOPED
:
2120 FIXME("unimplemented for type CMSG_ENVELOPED\n");
2124 if ((ret
= CDecodeMsg_DecodeSignedContent(msg
, blob
)))
2125 msg
->type
= CMSG_SIGNED
;
2129 CRYPT_CONTENT_INFO
*info
;
2132 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
,
2133 msg
->msg_data
.pbData
, msg
->msg_data
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
2134 NULL
, &info
, &size
);
2137 if (!strcmp(info
->pszObjId
, szOID_RSA_data
))
2138 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
, CMSG_DATA
);
2139 else if (!strcmp(info
->pszObjId
, szOID_RSA_digestedData
))
2140 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2142 else if (!strcmp(info
->pszObjId
, szOID_RSA_envelopedData
))
2143 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2145 else if (!strcmp(info
->pszObjId
, szOID_RSA_signedData
))
2146 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2150 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2160 static BOOL
CDecodeMsg_FinalizeHashedContent(CDecodeMsg
*msg
,
2161 CRYPT_DER_BLOB
*blob
)
2163 CRYPT_ALGORITHM_IDENTIFIER
*hashAlgoID
= NULL
;
2168 CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, NULL
, &size
);
2169 hashAlgoID
= CryptMemAlloc(size
);
2170 ret
= CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, hashAlgoID
,
2173 algID
= CertOIDToAlgId(hashAlgoID
->pszObjId
);
2174 ret
= CryptCreateHash(msg
->crypt_prov
, algID
, 0, 0, &msg
->u
.hash
);
2177 CRYPT_DATA_BLOB content
;
2179 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2181 /* Unlike for non-detached messages, the data were never stored as
2182 * the content param, but were saved in msg->detached_data instead.
2184 content
.pbData
= msg
->detached_data
.pbData
;
2185 content
.cbData
= msg
->detached_data
.cbData
;
2188 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2189 CMSG_CONTENT_PARAM
, &content
);
2191 ret
= CryptHashData(msg
->u
.hash
, content
.pbData
, content
.cbData
, 0);
2193 CryptMemFree(hashAlgoID
);
2197 static BOOL
CDecodeMsg_FinalizeSignedContent(CDecodeMsg
*msg
,
2198 CRYPT_DER_BLOB
*blob
)
2203 ret
= CSignedMsgData_AllocateHandles(&msg
->u
.signed_data
);
2204 for (i
= 0; ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
2205 ret
= CSignedMsgData_ConstructSignerHandles(&msg
->u
.signed_data
, i
,
2209 CRYPT_DATA_BLOB
*content
;
2211 /* Now that we have all the content, update the hash handles with
2212 * it. If the message is a detached message, the content is stored
2213 * in msg->detached_data rather than in the signed message's
2216 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2217 content
= &msg
->detached_data
;
2219 content
= &msg
->u
.signed_data
.info
->content
.Content
;
2220 if (content
->cbData
)
2222 /* If the message is not detached, have to decode the message's
2223 * content if the type is szOID_RSA_data.
2225 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) &&
2226 !strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2229 CRYPT_DATA_BLOB
*blob
;
2231 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
,
2232 X509_OCTET_STRING
, content
->pbData
, content
->cbData
,
2233 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &blob
, &size
);
2236 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2237 blob
->pbData
, blob
->cbData
, TRUE
, Verify
);
2242 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2243 content
->pbData
, content
->cbData
, TRUE
, Verify
);
2249 static BOOL
CDecodeMsg_FinalizeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
2256 ret
= CDecodeMsg_FinalizeHashedContent(msg
, blob
);
2259 ret
= CDecodeMsg_FinalizeSignedContent(msg
, blob
);
2267 static BOOL
CDecodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
2268 DWORD cbData
, BOOL fFinal
)
2270 CDecodeMsg
*msg
= hCryptMsg
;
2273 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
2275 if (msg
->base
.state
== MsgStateFinalized
)
2276 SetLastError(CRYPT_E_MSG_ERROR
);
2277 else if (msg
->base
.streamed
)
2279 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg
, pbData
,
2281 switch (msg
->base
.state
)
2284 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2287 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2288 msg
->base
.state
= MsgStateDataFinalized
;
2290 msg
->base
.state
= MsgStateFinalized
;
2293 msg
->base
.state
= MsgStateUpdated
;
2295 case MsgStateUpdated
:
2296 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2299 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2300 msg
->base
.state
= MsgStateDataFinalized
;
2302 msg
->base
.state
= MsgStateFinalized
;
2305 case MsgStateDataFinalized
:
2306 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2308 msg
->base
.state
= MsgStateFinalized
;
2311 SetLastError(CRYPT_E_MSG_ERROR
);
2318 SetLastError(CRYPT_E_MSG_ERROR
);
2321 switch (msg
->base
.state
)
2324 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2325 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2326 msg
->base
.state
= MsgStateDataFinalized
;
2328 msg
->base
.state
= MsgStateFinalized
;
2330 case MsgStateDataFinalized
:
2331 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2332 msg
->base
.state
= MsgStateFinalized
;
2335 SetLastError(CRYPT_E_MSG_ERROR
);
2339 if (ret
&& fFinal
&&
2340 ((msg
->base
.open_flags
& CMSG_DETACHED_FLAG
&& msg
->base
.state
==
2341 MsgStateDataFinalized
) ||
2342 (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->base
.state
==
2343 MsgStateFinalized
)))
2344 ret
= CDecodeMsg_DecodeContent(msg
, &msg
->msg_data
, msg
->type
);
2345 if (ret
&& msg
->base
.state
== MsgStateFinalized
)
2346 ret
= CDecodeMsg_FinalizeContent(msg
, &msg
->msg_data
);
2350 static BOOL
CDecodeHashMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2351 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2355 switch (dwParamType
)
2357 case CMSG_TYPE_PARAM
:
2358 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2360 case CMSG_HASH_ALGORITHM_PARAM
:
2362 CRYPT_DATA_BLOB blob
;
2364 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2368 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2370 CRYPT_FixUpAlgorithmID(pvData
);
2373 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2376 case CMSG_COMPUTED_HASH_PARAM
:
2377 ret
= CryptGetHashParam(msg
->u
.hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
2381 CRYPT_DATA_BLOB blob
;
2383 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2386 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2388 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2394 /* nextData is an in/out parameter - on input it's the memory location in
2395 * which a copy of in's data should be made, and on output it's the memory
2396 * location immediately after out's copy of in's data.
2398 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB
*out
,
2399 const CRYPT_DATA_BLOB
*in
, LPBYTE
*nextData
)
2401 out
->cbData
= in
->cbData
;
2404 out
->pbData
= *nextData
;
2405 memcpy(out
->pbData
, in
->pbData
, in
->cbData
);
2406 *nextData
+= in
->cbData
;
2410 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
2411 const CRYPT_ALGORITHM_IDENTIFIER
*in
, LPBYTE
*nextData
)
2415 out
->pszObjId
= (LPSTR
)*nextData
;
2416 strcpy(out
->pszObjId
, in
->pszObjId
);
2417 *nextData
+= strlen(out
->pszObjId
) + 1;
2419 CRYPT_CopyBlob(&out
->Parameters
, &in
->Parameters
, nextData
);
2422 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES
*out
,
2423 const CRYPT_ATTRIBUTES
*in
, LPBYTE
*nextData
)
2425 out
->cAttr
= in
->cAttr
;
2430 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2431 out
->rgAttr
= (CRYPT_ATTRIBUTE
*)*nextData
;
2432 *nextData
+= in
->cAttr
* sizeof(CRYPT_ATTRIBUTE
);
2433 for (i
= 0; i
< in
->cAttr
; i
++)
2435 if (in
->rgAttr
[i
].pszObjId
)
2437 out
->rgAttr
[i
].pszObjId
= (LPSTR
)*nextData
;
2438 strcpy(out
->rgAttr
[i
].pszObjId
, in
->rgAttr
[i
].pszObjId
);
2439 *nextData
+= strlen(in
->rgAttr
[i
].pszObjId
) + 1;
2441 if (in
->rgAttr
[i
].cValue
)
2445 out
->rgAttr
[i
].cValue
= in
->rgAttr
[i
].cValue
;
2446 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2447 out
->rgAttr
[i
].rgValue
= (PCRYPT_DATA_BLOB
)*nextData
;
2448 *nextData
+= in
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2449 for (j
= 0; j
< in
->rgAttr
[i
].cValue
; j
++)
2450 CRYPT_CopyBlob(&out
->rgAttr
[i
].rgValue
[j
],
2451 &in
->rgAttr
[i
].rgValue
[j
], nextData
);
2457 static DWORD
CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES
*attr
)
2459 DWORD size
= attr
->cAttr
* sizeof(CRYPT_ATTRIBUTE
), i
, j
;
2461 for (i
= 0; i
< attr
->cAttr
; i
++)
2463 if (attr
->rgAttr
[i
].pszObjId
)
2464 size
+= strlen(attr
->rgAttr
[i
].pszObjId
) + 1;
2466 size
= ALIGN_DWORD_PTR(size
);
2467 size
+= attr
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2468 for (j
= 0; j
< attr
->rgAttr
[i
].cValue
; j
++)
2469 size
+= attr
->rgAttr
[i
].rgValue
[j
].cbData
;
2471 /* align pointer again to be conservative */
2472 size
= ALIGN_DWORD_PTR(size
);
2476 static DWORD
CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB
*keyId
)
2478 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2481 CERT_RDN rdn
= { 1, &attr
};
2482 CERT_NAME_INFO name
= { 1, &rdn
};
2484 attr
.pszObjId
= oid_key_rdn
;
2485 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2486 attr
.Value
.cbData
= keyId
->cbData
;
2487 attr
.Value
.pbData
= keyId
->pbData
;
2488 if (CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, NULL
, &size
))
2489 size
++; /* Only include size of special zero serial number on success */
2493 static BOOL
CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB
*issuer
,
2494 CRYPT_INTEGER_BLOB
*serialNumber
, const CRYPT_DATA_BLOB
*keyId
, DWORD encodedLen
,
2497 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2499 CERT_RDN rdn
= { 1, &attr
};
2500 CERT_NAME_INFO name
= { 1, &rdn
};
2503 /* Encode special zero serial number */
2504 serialNumber
->cbData
= 1;
2505 serialNumber
->pbData
= *nextData
;
2509 issuer
->pbData
= *nextData
;
2510 attr
.pszObjId
= oid_key_rdn
;
2511 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2512 attr
.Value
.cbData
= keyId
->cbData
;
2513 attr
.Value
.pbData
= keyId
->pbData
;
2514 ret
= CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, *nextData
,
2518 *nextData
+= encodedLen
;
2519 issuer
->cbData
= encodedLen
;
2524 static BOOL
CRYPT_CopySignerInfo(void *pvData
, DWORD
*pcbData
,
2525 const CMSG_CMS_SIGNER_INFO
*in
)
2527 DWORD size
= sizeof(CMSG_SIGNER_INFO
), rdnSize
= 0;
2530 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2532 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2534 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2535 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2539 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2542 if (in
->HashAlgorithm
.pszObjId
)
2543 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2544 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2545 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2546 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2547 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2548 size
+= in
->EncryptedHash
.cbData
;
2550 size
= ALIGN_DWORD_PTR(size
);
2551 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2552 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2558 else if (*pcbData
< size
)
2561 SetLastError(ERROR_MORE_DATA
);
2566 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_SIGNER_INFO
);
2567 CMSG_SIGNER_INFO
*out
= pvData
;
2570 out
->dwVersion
= in
->dwVersion
;
2571 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2573 CRYPT_CopyBlob(&out
->Issuer
,
2574 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2575 CRYPT_CopyBlob(&out
->SerialNumber
,
2576 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2579 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2580 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2583 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2585 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2586 &in
->HashEncryptionAlgorithm
, &nextData
);
2587 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2588 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2589 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2590 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2593 TRACE("returning %d\n", ret
);
2597 static BOOL
CRYPT_CopyCMSSignerInfo(void *pvData
, DWORD
*pcbData
,
2598 const CMSG_CMS_SIGNER_INFO
*in
)
2600 DWORD size
= sizeof(CMSG_CMS_SIGNER_INFO
);
2603 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2605 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2607 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2608 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2611 size
+= in
->SignerId
.u
.KeyId
.cbData
;
2612 if (in
->HashAlgorithm
.pszObjId
)
2613 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2614 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2615 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2616 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2617 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2618 size
+= in
->EncryptedHash
.cbData
;
2620 size
= ALIGN_DWORD_PTR(size
);
2621 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2622 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2628 else if (*pcbData
< size
)
2631 SetLastError(ERROR_MORE_DATA
);
2636 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_CMS_SIGNER_INFO
);
2637 CMSG_CMS_SIGNER_INFO
*out
= pvData
;
2639 out
->dwVersion
= in
->dwVersion
;
2640 out
->SignerId
.dwIdChoice
= in
->SignerId
.dwIdChoice
;
2641 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2643 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
2644 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2645 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
2646 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2649 CRYPT_CopyBlob(&out
->SignerId
.u
.KeyId
, &in
->SignerId
.u
.KeyId
, &nextData
);
2650 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2652 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2653 &in
->HashEncryptionAlgorithm
, &nextData
);
2654 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2655 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2656 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2657 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2660 TRACE("returning %d\n", ret
);
2664 static BOOL
CRYPT_CopySignerCertInfo(void *pvData
, DWORD
*pcbData
,
2665 const CMSG_CMS_SIGNER_INFO
*in
)
2667 DWORD size
= sizeof(CERT_INFO
), rdnSize
= 0;
2670 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2672 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2674 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2675 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2679 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2687 else if (*pcbData
< size
)
2690 SetLastError(ERROR_MORE_DATA
);
2695 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2696 CERT_INFO
*out
= pvData
;
2698 memset(out
, 0, sizeof(CERT_INFO
));
2699 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2701 CRYPT_CopyBlob(&out
->Issuer
,
2702 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2703 CRYPT_CopyBlob(&out
->SerialNumber
,
2704 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2708 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2709 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2711 TRACE("returning %d\n", ret
);
2715 static BOOL
CDecodeSignedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2716 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2720 switch (dwParamType
)
2722 case CMSG_TYPE_PARAM
:
2723 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2725 case CMSG_CONTENT_PARAM
:
2726 if (msg
->u
.signed_data
.info
)
2728 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2731 CRYPT_DATA_BLOB
*blob
;
2734 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
2735 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
2736 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
2737 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &blob
, &size
);
2740 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
->pbData
,
2746 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2747 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
2748 msg
->u
.signed_data
.info
->content
.Content
.cbData
);
2751 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2753 case CMSG_INNER_CONTENT_TYPE_PARAM
:
2754 if (msg
->u
.signed_data
.info
)
2755 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2756 msg
->u
.signed_data
.info
->content
.pszObjId
,
2757 strlen(msg
->u
.signed_data
.info
->content
.pszObjId
) + 1);
2759 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2761 case CMSG_SIGNER_COUNT_PARAM
:
2762 if (msg
->u
.signed_data
.info
)
2763 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2764 &msg
->u
.signed_data
.info
->cSignerInfo
, sizeof(DWORD
));
2766 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2768 case CMSG_SIGNER_INFO_PARAM
:
2769 if (msg
->u
.signed_data
.info
)
2771 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2772 SetLastError(CRYPT_E_INVALID_INDEX
);
2774 ret
= CRYPT_CopySignerInfo(pvData
, pcbData
,
2775 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
2778 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2780 case CMSG_SIGNER_CERT_INFO_PARAM
:
2781 if (msg
->u
.signed_data
.info
)
2783 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2784 SetLastError(CRYPT_E_INVALID_INDEX
);
2786 ret
= CRYPT_CopySignerCertInfo(pvData
, pcbData
,
2787 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
2790 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2792 case CMSG_CERT_COUNT_PARAM
:
2793 if (msg
->u
.signed_data
.info
)
2794 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2795 &msg
->u
.signed_data
.info
->cCertEncoded
, sizeof(DWORD
));
2797 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2799 case CMSG_CERT_PARAM
:
2800 if (msg
->u
.signed_data
.info
)
2802 if (dwIndex
>= msg
->u
.signed_data
.info
->cCertEncoded
)
2803 SetLastError(CRYPT_E_INVALID_INDEX
);
2805 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2806 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].pbData
,
2807 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].cbData
);
2810 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2812 case CMSG_CRL_COUNT_PARAM
:
2813 if (msg
->u
.signed_data
.info
)
2814 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2815 &msg
->u
.signed_data
.info
->cCrlEncoded
, sizeof(DWORD
));
2817 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2819 case CMSG_CRL_PARAM
:
2820 if (msg
->u
.signed_data
.info
)
2822 if (dwIndex
>= msg
->u
.signed_data
.info
->cCrlEncoded
)
2823 SetLastError(CRYPT_E_INVALID_INDEX
);
2825 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2826 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].pbData
,
2827 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].cbData
);
2830 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2832 case CMSG_COMPUTED_HASH_PARAM
:
2833 if (msg
->u
.signed_data
.info
)
2835 if (dwIndex
>= msg
->u
.signed_data
.cSignerHandle
)
2836 SetLastError(CRYPT_E_INVALID_INDEX
);
2838 ret
= CryptGetHashParam(
2839 msg
->u
.signed_data
.signerHandles
[dwIndex
].contentHash
,
2840 HP_HASHVAL
, pvData
, pcbData
, 0);
2843 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2845 case CMSG_ENCODED_SIGNER
:
2846 if (msg
->u
.signed_data
.info
)
2848 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2849 SetLastError(CRYPT_E_INVALID_INDEX
);
2851 ret
= CryptEncodeObjectEx(
2852 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, CMS_SIGNER_INFO
,
2853 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
], 0, NULL
,
2857 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2859 case CMSG_ATTR_CERT_COUNT_PARAM
:
2860 if (msg
->u
.signed_data
.info
)
2862 DWORD attrCertCount
= 0;
2864 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2865 &attrCertCount
, sizeof(DWORD
));
2868 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2870 case CMSG_ATTR_CERT_PARAM
:
2871 if (msg
->u
.signed_data
.info
)
2872 SetLastError(CRYPT_E_INVALID_INDEX
);
2874 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2876 case CMSG_CMS_SIGNER_INFO_PARAM
:
2877 if (msg
->u
.signed_data
.info
)
2879 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
2880 SetLastError(CRYPT_E_INVALID_INDEX
);
2882 ret
= CRYPT_CopyCMSSignerInfo(pvData
, pcbData
,
2883 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
2886 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2889 FIXME("unimplemented for %d\n", dwParamType
);
2890 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2895 static BOOL
CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
2896 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2898 CDecodeMsg
*msg
= hCryptMsg
;
2904 ret
= CDecodeHashMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2908 ret
= CDecodeSignedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
2912 switch (dwParamType
)
2914 case CMSG_TYPE_PARAM
:
2915 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
,
2920 CRYPT_DATA_BLOB blob
;
2922 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2925 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
,
2928 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2935 static BOOL
CDecodeHashMsg_VerifyHash(CDecodeMsg
*msg
)
2938 CRYPT_DATA_BLOB hashBlob
;
2940 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2941 CMSG_HASH_DATA_PARAM
, &hashBlob
);
2944 DWORD computedHashSize
= 0;
2946 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
,
2948 if (hashBlob
.cbData
== computedHashSize
)
2950 LPBYTE computedHash
= CryptMemAlloc(computedHashSize
);
2954 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
2955 computedHash
, &computedHashSize
);
2958 if (memcmp(hashBlob
.pbData
, computedHash
, hashBlob
.cbData
))
2960 SetLastError(CRYPT_E_HASH_VALUE
);
2964 CryptMemFree(computedHash
);
2968 SetLastError(ERROR_OUTOFMEMORY
);
2974 SetLastError(CRYPT_E_HASH_VALUE
);
2981 static BOOL
CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg
*msg
,
2982 HCRYPTPROV prov
, DWORD signerIndex
, PCERT_PUBLIC_KEY_INFO keyInfo
)
2988 prov
= msg
->crypt_prov
;
2989 ret
= CryptImportPublicKeyInfo(prov
, X509_ASN_ENCODING
, keyInfo
, &key
);
2993 CRYPT_HASH_BLOB reversedHash
;
2995 if (msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
)
2996 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].authAttrHash
;
2998 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].contentHash
;
2999 ret
= CRYPT_ConstructBlob(&reversedHash
,
3000 &msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].EncryptedHash
);
3003 CRYPT_ReverseBytes(&reversedHash
);
3004 ret
= CryptVerifySignatureW(hash
, reversedHash
.pbData
,
3005 reversedHash
.cbData
, key
, NULL
, 0);
3006 CryptMemFree(reversedHash
.pbData
);
3008 CryptDestroyKey(key
);
3013 static BOOL
CDecodeSignedMsg_VerifySignature(CDecodeMsg
*msg
, PCERT_INFO info
)
3018 if (!msg
->u
.signed_data
.signerHandles
)
3020 SetLastError(NTE_BAD_SIGNATURE
);
3023 for (i
= 0; !ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
3025 PCMSG_CMS_SIGNER_INFO signerInfo
=
3026 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
];
3028 if (signerInfo
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
3030 ret
= CertCompareCertificateName(X509_ASN_ENCODING
,
3031 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
3035 ret
= CertCompareIntegerBlob(
3036 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
3037 &info
->SerialNumber
);
3044 FIXME("signer %d: unimplemented for key id\n", i
);
3048 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, 0, i
,
3049 &info
->SubjectPublicKeyInfo
);
3051 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3056 static BOOL
CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg
*msg
,
3057 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para
)
3061 if (para
->cbSize
!= sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
))
3062 SetLastError(ERROR_INVALID_PARAMETER
);
3063 else if (para
->dwSignerIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3064 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3065 else if (!msg
->u
.signed_data
.signerHandles
)
3066 SetLastError(NTE_BAD_SIGNATURE
);
3069 switch (para
->dwSignerType
)
3071 case CMSG_VERIFY_SIGNER_PUBKEY
:
3072 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
,
3073 para
->hCryptProv
, para
->dwSignerIndex
, para
->pvSigner
);
3075 case CMSG_VERIFY_SIGNER_CERT
:
3077 PCCERT_CONTEXT cert
= para
->pvSigner
;
3079 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, para
->hCryptProv
,
3080 para
->dwSignerIndex
, &cert
->pCertInfo
->SubjectPublicKeyInfo
);
3084 FIXME("unimplemented for signer type %d\n", para
->dwSignerType
);
3085 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3091 static BOOL
CDecodeMsg_Control(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3092 DWORD dwCtrlType
, const void *pvCtrlPara
)
3094 CDecodeMsg
*msg
= hCryptMsg
;
3099 case CMSG_CTRL_VERIFY_SIGNATURE
:
3103 ret
= CDecodeSignedMsg_VerifySignature(msg
, (PCERT_INFO
)pvCtrlPara
);
3106 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3109 case CMSG_CTRL_DECRYPT
:
3113 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3116 case CMSG_CTRL_VERIFY_HASH
:
3120 ret
= CDecodeHashMsg_VerifyHash(msg
);
3123 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3126 case CMSG_CTRL_VERIFY_SIGNATURE_EX
:
3130 ret
= CDecodeSignedMsg_VerifySignatureEx(msg
,
3131 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
)pvCtrlPara
);
3134 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3138 SetLastError(CRYPT_E_CONTROL_TYPE
);
3143 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
3144 DWORD dwMsgType
, HCRYPTPROV_LEGACY hCryptProv
, PCERT_INFO pRecipientInfo
,
3145 PCMSG_STREAM_INFO pStreamInfo
)
3149 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType
,
3150 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
3152 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
3154 SetLastError(E_INVALIDARG
);
3157 msg
= CryptMemAlloc(sizeof(CDecodeMsg
));
3160 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
3161 CDecodeMsg_Close
, CDecodeMsg_GetParam
, CDecodeMsg_Update
,
3162 CDecodeMsg_Control
);
3163 msg
->type
= dwMsgType
;
3165 msg
->crypt_prov
= hCryptProv
;
3168 msg
->crypt_prov
= CRYPT_GetDefaultProvider();
3169 msg
->base
.open_flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
3171 memset(&msg
->u
, 0, sizeof(msg
->u
));
3172 msg
->msg_data
.cbData
= 0;
3173 msg
->msg_data
.pbData
= NULL
;
3174 msg
->detached_data
.cbData
= 0;
3175 msg
->detached_data
.pbData
= NULL
;
3176 msg
->properties
= ContextPropertyList_Create();
3181 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
3183 TRACE("(%p)\n", hCryptMsg
);
3187 CryptMsgBase
*msg
= hCryptMsg
;
3189 InterlockedIncrement(&msg
->ref
);
3194 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
3196 TRACE("(%p)\n", hCryptMsg
);
3200 CryptMsgBase
*msg
= hCryptMsg
;
3202 if (InterlockedDecrement(&msg
->ref
) == 0)
3204 TRACE("freeing %p\n", msg
);
3213 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
3214 DWORD cbData
, BOOL fFinal
)
3216 CryptMsgBase
*msg
= hCryptMsg
;
3218 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
3220 return msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
3223 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
3224 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3226 CryptMsgBase
*msg
= hCryptMsg
;
3228 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
3230 return msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);
3233 BOOL WINAPI
CryptMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3234 DWORD dwCtrlType
, const void *pvCtrlPara
)
3236 CryptMsgBase
*msg
= hCryptMsg
;
3238 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
,
3240 return msg
->control(hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
3243 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
3244 DWORD dwSignerIndex
)
3246 CERT_INFO
*certInfo
= NULL
;
3249 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
3252 certInfo
= CryptMemAlloc(size
);
3255 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
3256 dwSignerIndex
, certInfo
, &size
))
3258 CryptMemFree(certInfo
);
3266 BOOL WINAPI
CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg
, DWORD cSignerStore
,
3267 HCERTSTORE
*rghSignerStore
, DWORD dwFlags
, PCCERT_CONTEXT
*ppSigner
,
3268 DWORD
*pdwSignerIndex
)
3271 DWORD i
, signerIndex
= 0;
3272 PCCERT_CONTEXT signerCert
= NULL
;
3275 TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg
, cSignerStore
,
3276 rghSignerStore
, dwFlags
, ppSigner
, pdwSignerIndex
);
3278 /* Clear output parameters */
3281 if (pdwSignerIndex
&& !(dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
))
3282 *pdwSignerIndex
= 0;
3284 /* Create store to search for signer certificates */
3285 store
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
3286 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
3287 if (!(dwFlags
& CMSG_TRUSTED_SIGNER_FLAG
))
3289 HCERTSTORE msgStore
= CertOpenStore(CERT_STORE_PROV_MSG
, 0, 0, 0,
3292 CertAddStoreToCollection(store
, msgStore
, 0, 0);
3293 CertCloseStore(msgStore
, 0);
3295 for (i
= 0; i
< cSignerStore
; i
++)
3296 CertAddStoreToCollection(store
, rghSignerStore
[i
], 0, 0);
3298 /* Find signer cert */
3299 if (dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
)
3301 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3306 signerIndex
= *pdwSignerIndex
;
3307 signerCert
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
,
3308 0, CERT_FIND_SUBJECT_CERT
, signer
, NULL
);
3309 CryptMemFree(signer
);
3314 DWORD count
, size
= sizeof(count
);
3316 if (CryptMsgGetParam(hCryptMsg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
,
3319 for (i
= 0; !signerCert
&& i
< count
; i
++)
3321 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3326 signerCert
= CertFindCertificateInStore(store
,
3327 X509_ASN_ENCODING
, 0, CERT_FIND_SUBJECT_CERT
, signer
,
3331 CryptMemFree(signer
);
3336 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER
);
3340 if (!(dwFlags
& CMSG_SIGNER_ONLY_FLAG
))
3341 ret
= CryptMsgControl(hCryptMsg
, 0, CMSG_CTRL_VERIFY_SIGNATURE
,
3342 signerCert
->pCertInfo
);
3348 *ppSigner
= CertDuplicateCertificateContext(signerCert
);
3350 *pdwSignerIndex
= signerIndex
;
3352 CertFreeCertificateContext(signerCert
);
3355 CertCloseStore(store
, 0);
3359 BOOL WINAPI
CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv
,
3360 DWORD dwEncodingType
, PBYTE pbSignerInfo
, DWORD cbSignerInfo
,
3361 PBYTE pbSignerInfoCountersignature
, DWORD cbSignerInfoCountersignature
,
3362 DWORD dwSignerType
, void *pvSigner
, DWORD dwFlags
, void *pvReserved
)
3364 FIXME("(%08lx, %08x, %p, %d, %p, %d, %d, %p, %08x, %p): stub\n", hCryptProv
,
3365 dwEncodingType
, pbSignerInfo
, cbSignerInfo
, pbSignerInfoCountersignature
,
3366 cbSignerInfoCountersignature
, dwSignerType
, pvSigner
, dwFlags
, pvReserved
);
3370 BOOL WINAPI
CryptMsgEncodeAndSignCTL(DWORD dwMsgEncodingType
,
3371 PCTL_INFO pCtlInfo
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3372 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3378 TRACE("(%08x, %p, %p, %08x, %p, %p)\n", dwMsgEncodingType
, pCtlInfo
,
3379 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3383 FIXME("unimplemented for flags %08x\n", dwFlags
);
3386 if ((ret
= CryptEncodeObjectEx(dwMsgEncodingType
, PKCS_CTL
, pCtlInfo
,
3387 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &pbCtlContent
, &cbCtlContent
)))
3389 ret
= CryptMsgSignCTL(dwMsgEncodingType
, pbCtlContent
, cbCtlContent
,
3390 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3391 LocalFree(pbCtlContent
);
3396 BOOL WINAPI
CryptMsgSignCTL(DWORD dwMsgEncodingType
, BYTE
*pbCtlContent
,
3397 DWORD cbCtlContent
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3398 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3400 static char oid_ctl
[] = szOID_CTL
;
3404 TRACE("(%08x, %p, %d, %p, %08x, %p, %p)\n", dwMsgEncodingType
,
3405 pbCtlContent
, cbCtlContent
, pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3409 FIXME("unimplemented for flags %08x\n", dwFlags
);
3412 msg
= CryptMsgOpenToEncode(dwMsgEncodingType
, 0, CMSG_SIGNED
, pSignInfo
,
3416 ret
= CryptMsgUpdate(msg
, pbCtlContent
, cbCtlContent
, TRUE
);
3418 ret
= CryptMsgGetParam(msg
, CMSG_CONTENT_PARAM
, 0, pbEncoded
,