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 #define NONAMELESSUNION
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
CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
47 DWORD dwCtrlType
, const void *pvCtrlPara
)
49 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
50 SetLastError(E_INVALIDARG
);
54 typedef enum _CryptMsgState
{
57 MsgStateDataFinalized
,
61 typedef struct _CryptMsgBase
66 CMSG_STREAM_INFO stream_info
;
68 CryptMsgCloseFunc close
;
69 CryptMsgUpdateFunc update
;
70 CryptMsgGetParamFunc get_param
;
71 CryptMsgControlFunc control
;
74 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
75 PCMSG_STREAM_INFO pStreamInfo
, CryptMsgCloseFunc close
,
76 CryptMsgGetParamFunc get_param
, CryptMsgUpdateFunc update
,
77 CryptMsgControlFunc control
)
80 msg
->open_flags
= dwFlags
;
84 msg
->stream_info
= *pStreamInfo
;
88 msg
->streamed
= FALSE
;
89 memset(&msg
->stream_info
, 0, sizeof(msg
->stream_info
));
92 msg
->get_param
= get_param
;
94 msg
->control
= control
;
95 msg
->state
= MsgStateInit
;
98 typedef struct _CDataEncodeMsg
101 DWORD bare_content_len
;
105 static const BYTE empty_data_content
[] = { 0x04,0x00 };
107 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
109 CDataEncodeMsg
*msg
= hCryptMsg
;
111 if (msg
->bare_content
!= empty_data_content
)
112 LocalFree(msg
->bare_content
);
115 static BOOL WINAPI
CRYPT_EncodeContentLength(DWORD dwCertEncodingType
,
116 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
117 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
119 DWORD dataLen
= *(DWORD
*)pvStructInfo
;
123 /* Trick: report bytes needed based on total message length, even though
124 * the message isn't available yet. The caller will use the length
125 * reported here to encode its length.
127 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
129 *pcbEncoded
= 1 + lenBytes
+ dataLen
;
132 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
133 pcbEncoded
, 1 + lenBytes
)))
135 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
136 pbEncoded
= *(BYTE
**)pbEncoded
;
137 *pbEncoded
++ = ASN_OCTETSTRING
;
138 CRYPT_EncodeLen(dataLen
, pbEncoded
,
145 static BOOL
CRYPT_EncodeDataContentInfoHeader(const CDataEncodeMsg
*msg
,
146 CRYPT_DATA_BLOB
*header
)
150 if (msg
->base
.streamed
&& msg
->base
.stream_info
.cbContent
== 0xffffffff)
152 static const BYTE headerValue
[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
153 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
155 header
->pbData
= LocalAlloc(0, sizeof(headerValue
));
158 header
->cbData
= sizeof(headerValue
);
159 memcpy(header
->pbData
, headerValue
, sizeof(headerValue
));
167 struct AsnConstructedItem constructed
= { 0,
168 &msg
->base
.stream_info
.cbContent
, CRYPT_EncodeContentLength
};
169 struct AsnEncodeSequenceItem items
[2] = {
170 { szOID_RSA_data
, CRYPT_AsnEncodeOid
, 0 },
171 { &constructed
, CRYPT_AsnEncodeConstructed
, 0 },
174 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
175 ARRAY_SIZE(items
), CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
176 (LPBYTE
)&header
->pbData
, &header
->cbData
);
179 /* Trick: subtract the content length from the reported length,
180 * as the actual content hasn't come yet.
182 header
->cbData
-= msg
->base
.stream_info
.cbContent
;
188 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
189 DWORD cbData
, BOOL fFinal
)
191 CDataEncodeMsg
*msg
= hCryptMsg
;
194 if (msg
->base
.state
== MsgStateFinalized
)
195 SetLastError(CRYPT_E_MSG_ERROR
);
196 else if (msg
->base
.streamed
)
200 if (msg
->base
.state
!= MsgStateUpdated
)
202 CRYPT_DATA_BLOB header
;
204 ret
= CRYPT_EncodeDataContentInfoHeader(msg
, &header
);
207 ret
= msg
->base
.stream_info
.pfnStreamOutput(
208 msg
->base
.stream_info
.pvArg
, header
.pbData
, header
.cbData
,
210 LocalFree(header
.pbData
);
213 /* Curiously, every indefinite-length streamed update appears to
214 * get its own tag and length, regardless of fFinal.
216 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
221 ret
= CRYPT_EncodeContentLength(X509_ASN_ENCODING
, NULL
,
222 &cbData
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (BYTE
*)&header
,
226 ret
= msg
->base
.stream_info
.pfnStreamOutput(
227 msg
->base
.stream_info
.pvArg
, header
, headerLen
,
234 ret
= msg
->base
.stream_info
.pfnStreamOutput(
235 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
237 msg
->base
.state
= MsgStateUpdated
;
241 msg
->base
.state
= MsgStateFinalized
;
242 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
244 BYTE indefinite_trailer
[6] = { 0 };
246 ret
= msg
->base
.stream_info
.pfnStreamOutput(
247 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
250 ret
= msg
->base
.stream_info
.pfnStreamOutput(
251 msg
->base
.stream_info
.pvArg
, indefinite_trailer
,
252 sizeof(indefinite_trailer
), TRUE
);
255 ret
= msg
->base
.stream_info
.pfnStreamOutput(
256 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
, TRUE
);
261 SetLastError(STATUS_ACCESS_VIOLATION
);
270 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
271 SetLastError(E_INVALIDARG
);
273 SetLastError(CRYPT_E_MSG_ERROR
);
277 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
279 msg
->base
.state
= MsgStateFinalized
;
280 /* non-streamed data messages don't allow non-final updates,
281 * don't bother checking whether data already exist, they can't.
283 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
284 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
285 &msg
->bare_content_len
);
291 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
298 else if (*pcbData
< len
)
301 SetLastError(ERROR_MORE_DATA
);
307 memcpy(pvData
, src
, len
);
312 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
313 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
315 CDataEncodeMsg
*msg
= hCryptMsg
;
320 case CMSG_CONTENT_PARAM
:
321 if (msg
->base
.streamed
)
322 SetLastError(E_INVALIDARG
);
325 CRYPT_CONTENT_INFO info
;
326 char rsa_data
[] = "1.2.840.113549.1.7.1";
328 info
.pszObjId
= rsa_data
;
329 info
.Content
.cbData
= msg
->bare_content_len
;
330 info
.Content
.pbData
= msg
->bare_content
;
331 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
335 case CMSG_BARE_CONTENT_PARAM
:
336 if (msg
->base
.streamed
)
337 SetLastError(E_INVALIDARG
);
339 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->bare_content
,
340 msg
->bare_content_len
);
343 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
348 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
349 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
355 SetLastError(E_INVALIDARG
);
358 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
361 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
362 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
,
363 CRYPT_DefaultMsgControl
);
364 msg
->bare_content_len
= sizeof(empty_data_content
);
365 msg
->bare_content
= (LPBYTE
)empty_data_content
;
370 typedef struct _CHashEncodeMsg
375 CRYPT_DATA_BLOB data
;
378 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
380 CHashEncodeMsg
*msg
= hCryptMsg
;
382 CryptMemFree(msg
->data
.pbData
);
383 CryptDestroyHash(msg
->hash
);
384 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
385 CryptReleaseContext(msg
->prov
, 0);
388 static BOOL
CRYPT_EncodePKCSDigestedData(CHashEncodeMsg
*msg
, void *pvData
,
393 DWORD size
= sizeof(algID
);
395 ret
= CryptGetHashParam(msg
->hash
, HP_ALGID
, (BYTE
*)&algID
, &size
, 0);
398 CRYPT_DIGESTED_DATA digestedData
= { 0 };
399 char oid_rsa_data
[] = szOID_RSA_data
;
401 digestedData
.version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
402 digestedData
.DigestAlgorithm
.pszObjId
= (LPSTR
)CertAlgIdToOID(algID
);
403 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
404 /* Quirk: OID is only encoded messages if an update has happened */
405 if (msg
->base
.state
!= MsgStateInit
)
406 digestedData
.ContentInfo
.pszObjId
= oid_rsa_data
;
407 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->data
.cbData
)
409 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &msg
->data
,
410 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
411 (LPBYTE
)&digestedData
.ContentInfo
.Content
.pbData
,
412 &digestedData
.ContentInfo
.Content
.cbData
);
414 if (msg
->base
.state
== MsgStateFinalized
)
416 size
= sizeof(DWORD
);
417 ret
= CryptGetHashParam(msg
->hash
, HP_HASHSIZE
,
418 (LPBYTE
)&digestedData
.hash
.cbData
, &size
, 0);
421 digestedData
.hash
.pbData
= CryptMemAlloc(
422 digestedData
.hash
.cbData
);
423 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
,
424 digestedData
.hash
.pbData
, &digestedData
.hash
.cbData
, 0);
428 ret
= CRYPT_AsnEncodePKCSDigestedData(&digestedData
, pvData
,
430 CryptMemFree(digestedData
.hash
.pbData
);
431 LocalFree(digestedData
.ContentInfo
.Content
.pbData
);
436 static BOOL
CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
437 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
439 CHashEncodeMsg
*msg
= hCryptMsg
;
442 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
447 case CMSG_BARE_CONTENT_PARAM
:
448 if (msg
->base
.streamed
)
449 SetLastError(E_INVALIDARG
);
451 ret
= CRYPT_EncodePKCSDigestedData(msg
, pvData
, pcbData
);
453 case CMSG_CONTENT_PARAM
:
455 CRYPT_CONTENT_INFO info
;
457 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
458 &info
.Content
.cbData
);
461 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
462 if (info
.Content
.pbData
)
464 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
465 info
.Content
.pbData
, &info
.Content
.cbData
);
468 char oid_rsa_hashed
[] = szOID_RSA_hashedData
;
470 info
.pszObjId
= oid_rsa_hashed
;
471 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
472 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
474 CryptMemFree(info
.Content
.pbData
);
481 case CMSG_COMPUTED_HASH_PARAM
:
482 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
484 case CMSG_VERSION_PARAM
:
485 if (msg
->base
.state
!= MsgStateFinalized
)
486 SetLastError(CRYPT_E_MSG_ERROR
);
489 DWORD version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
491 /* Since the data are always encoded as octets, the version is
492 * always 0 (see rfc3852, section 7)
494 ret
= CRYPT_CopyParam(pvData
, pcbData
, &version
, sizeof(version
));
498 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
503 static BOOL
CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
504 DWORD cbData
, BOOL fFinal
)
506 CHashEncodeMsg
*msg
= hCryptMsg
;
509 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
511 if (msg
->base
.state
== MsgStateFinalized
)
512 SetLastError(CRYPT_E_MSG_ERROR
);
513 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
515 /* Doesn't do much, as stream output is never called, and you
516 * can't get the content.
518 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
519 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
524 SetLastError(CRYPT_E_MSG_ERROR
);
527 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
530 msg
->data
.pbData
= CryptMemAlloc(cbData
);
531 if (msg
->data
.pbData
)
533 memcpy(msg
->data
.pbData
+ msg
->data
.cbData
, pbData
, cbData
);
534 msg
->data
.cbData
+= cbData
;
539 msg
->base
.state
= MsgStateFinalized
;
545 static HCRYPTMSG
CHashEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
546 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
549 const CMSG_HASHED_ENCODE_INFO
*info
= pvMsgEncodeInfo
;
553 if (info
->cbSize
!= sizeof(CMSG_HASHED_ENCODE_INFO
))
555 SetLastError(E_INVALIDARG
);
558 if (!(algID
= CertOIDToAlgId(info
->HashAlgorithm
.pszObjId
)))
560 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
563 if (info
->hCryptProv
)
564 prov
= info
->hCryptProv
;
567 prov
= I_CryptGetDefaultCryptProv(algID
);
570 SetLastError(E_INVALIDARG
);
573 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
575 msg
= CryptMemAlloc(sizeof(CHashEncodeMsg
));
578 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
579 CHashEncodeMsg_Close
, CHashEncodeMsg_GetParam
, CHashEncodeMsg_Update
,
580 CRYPT_DefaultMsgControl
);
582 msg
->data
.cbData
= 0;
583 msg
->data
.pbData
= NULL
;
584 if (!CryptCreateHash(prov
, algID
, 0, 0, &msg
->hash
))
593 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
596 PCERT_INFO pCertInfo
;
597 HCRYPTPROV hCryptProv
;
599 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm
;
602 PCRYPT_ATTRIBUTE rgAuthAttr
;
604 PCRYPT_ATTRIBUTE rgUnauthAttr
;
606 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm
;
607 void *pvHashEncryptionAuxInfo
;
608 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS
;
610 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
614 CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*rgSigners
;
616 PCERT_BLOB rgCertEncoded
;
618 PCRL_BLOB rgCrlEncoded
;
619 DWORD cAttrCertEncoded
;
620 PCERT_BLOB rgAttrCertEncoded
;
621 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS
;
623 static BOOL
CRYPT_IsValidSigner(const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*signer
)
625 if (signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO
) &&
626 signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
628 SetLastError(E_INVALIDARG
);
631 if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
633 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
635 SetLastError(E_INVALIDARG
);
638 if (!signer
->pCertInfo
->Issuer
.cbData
)
640 SetLastError(E_INVALIDARG
);
644 else if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
646 switch (signer
->SignerId
.dwIdChoice
)
649 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
651 SetLastError(E_INVALIDARG
);
654 if (!signer
->pCertInfo
->Issuer
.cbData
)
656 SetLastError(E_INVALIDARG
);
660 case CERT_ID_ISSUER_SERIAL_NUMBER
:
661 if (!signer
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
)
663 SetLastError(E_INVALIDARG
);
666 if (!signer
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
668 SetLastError(E_INVALIDARG
);
672 case CERT_ID_KEY_IDENTIFIER
:
673 if (!signer
->SignerId
.u
.KeyId
.cbData
)
675 SetLastError(E_INVALIDARG
);
680 SetLastError(E_INVALIDARG
);
682 if (signer
->HashEncryptionAlgorithm
.pszObjId
)
684 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
688 if (!signer
->hCryptProv
)
690 SetLastError(E_INVALIDARG
);
693 if (!CertOIDToAlgId(signer
->HashAlgorithm
.pszObjId
))
695 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
701 static BOOL
CRYPT_ConstructBlob(CRYPT_DATA_BLOB
*out
, const CRYPT_DATA_BLOB
*in
)
705 out
->cbData
= in
->cbData
;
708 out
->pbData
= CryptMemAlloc(out
->cbData
);
710 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
719 static BOOL
CRYPT_ConstructBlobArray(DWORD
*outCBlobs
,
720 PCRYPT_DATA_BLOB
*outPBlobs
, DWORD cBlobs
, const CRYPT_DATA_BLOB
*pBlobs
)
727 *outPBlobs
= CryptMemAlloc(cBlobs
* sizeof(CRYPT_DATA_BLOB
));
732 memset(*outPBlobs
, 0, cBlobs
* sizeof(CRYPT_DATA_BLOB
));
733 for (i
= 0; ret
&& i
< cBlobs
; i
++)
734 ret
= CRYPT_ConstructBlob(&(*outPBlobs
)[i
], &pBlobs
[i
]);
742 static void CRYPT_FreeBlobArray(DWORD cBlobs
, PCRYPT_DATA_BLOB blobs
)
746 for (i
= 0; i
< cBlobs
; i
++)
747 CryptMemFree(blobs
[i
].pbData
);
751 static BOOL
CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE
*out
,
752 const CRYPT_ATTRIBUTE
*in
)
756 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
759 strcpy(out
->pszObjId
, in
->pszObjId
);
760 ret
= CRYPT_ConstructBlobArray(&out
->cValue
, &out
->rgValue
,
761 in
->cValue
, in
->rgValue
);
768 static BOOL
CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES
*out
,
769 const CRYPT_ATTRIBUTES
*in
)
773 out
->cAttr
= in
->cAttr
;
776 out
->rgAttr
= CryptMemAlloc(out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
781 memset(out
->rgAttr
, 0, out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
782 for (i
= 0; ret
&& i
< out
->cAttr
; i
++)
783 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[i
], &in
->rgAttr
[i
]);
793 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
794 static BOOL
CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO
*info
,
795 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*in
)
799 if (in
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
801 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
802 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
803 &in
->pCertInfo
->Issuer
);
805 ret
= CRYPT_ConstructBlob(
806 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
807 &in
->pCertInfo
->SerialNumber
);
808 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
809 info
->HashEncryptionAlgorithm
.pszObjId
=
810 in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
;
812 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
813 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.Parameters
);
817 const CRYPT_ALGORITHM_IDENTIFIER
*pEncrAlg
;
819 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS).
820 * See CRYPT_IsValidSigner.
822 if (!in
->SignerId
.dwIdChoice
)
824 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
825 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
826 &in
->pCertInfo
->Issuer
);
828 ret
= CRYPT_ConstructBlob(
829 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
830 &in
->pCertInfo
->SerialNumber
);
831 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
833 else if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
835 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
836 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
837 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
838 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
);
840 ret
= CRYPT_ConstructBlob(
841 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
842 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
);
846 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */
847 info
->dwVersion
= CMSG_SIGNER_INFO_V3
;
848 info
->SignerId
.dwIdChoice
= CERT_ID_KEY_IDENTIFIER
;
849 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.KeyId
,
850 &in
->SignerId
.u
.KeyId
);
852 pEncrAlg
= in
->HashEncryptionAlgorithm
.pszObjId
?
853 &in
->HashEncryptionAlgorithm
:
854 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
;
855 info
->HashEncryptionAlgorithm
.pszObjId
= pEncrAlg
->pszObjId
;
857 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
858 &pEncrAlg
->Parameters
);
860 /* Assumption: algorithm IDs will point to static strings, not
861 * stack-based ones, so copying the pointer values is safe.
863 info
->HashAlgorithm
.pszObjId
= in
->HashAlgorithm
.pszObjId
;
865 ret
= CRYPT_ConstructBlob(&info
->HashAlgorithm
.Parameters
,
866 &in
->HashAlgorithm
.Parameters
);
868 ret
= CRYPT_ConstructAttributes(&info
->AuthAttrs
,
869 (CRYPT_ATTRIBUTES
*)&in
->cAuthAttr
);
871 ret
= CRYPT_ConstructAttributes(&info
->UnauthAttrs
,
872 (CRYPT_ATTRIBUTES
*)&in
->cUnauthAttr
);
876 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO
*info
)
880 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
882 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
883 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
886 CryptMemFree(info
->SignerId
.u
.KeyId
.pbData
);
887 CryptMemFree(info
->HashAlgorithm
.Parameters
.pbData
);
888 CryptMemFree(info
->HashEncryptionAlgorithm
.Parameters
.pbData
);
889 CryptMemFree(info
->EncryptedHash
.pbData
);
890 for (i
= 0; i
< info
->AuthAttrs
.cAttr
; i
++)
892 for (j
= 0; j
< info
->AuthAttrs
.rgAttr
[i
].cValue
; j
++)
893 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
894 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
);
895 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].pszObjId
);
897 CryptMemFree(info
->AuthAttrs
.rgAttr
);
898 for (i
= 0; i
< info
->UnauthAttrs
.cAttr
; i
++)
900 for (j
= 0; j
< info
->UnauthAttrs
.rgAttr
[i
].cValue
; j
++)
901 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
902 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
);
903 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].pszObjId
);
905 CryptMemFree(info
->UnauthAttrs
.rgAttr
);
908 typedef struct _CSignerHandles
910 HCRYPTHASH contentHash
;
911 HCRYPTHASH authAttrHash
;
914 typedef struct _CSignedMsgData
916 CRYPT_SIGNED_INFO
*info
;
918 CSignerHandles
*signerHandles
;
921 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
922 * Assumes signerIndex is a valid index, and that msg_data's info has already
925 static BOOL
CSignedMsgData_ConstructSignerHandles(CSignedMsgData
*msg_data
,
926 DWORD signerIndex
, HCRYPTPROV
*crypt_prov
, DWORD
*flags
)
931 algID
= CertOIDToAlgId(
932 msg_data
->info
->rgSignerInfo
[signerIndex
].HashAlgorithm
.pszObjId
);
936 *crypt_prov
= I_CryptGetDefaultCryptProv(algID
);
937 if (!*crypt_prov
) return FALSE
;
938 *flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
941 ret
= CryptCreateHash(*crypt_prov
, algID
, 0, 0,
942 &msg_data
->signerHandles
->contentHash
);
943 if (ret
&& msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
> 0)
944 ret
= CryptCreateHash(*crypt_prov
, algID
, 0, 0,
945 &msg_data
->signerHandles
->authAttrHash
);
949 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
952 static BOOL
CSignedMsgData_AllocateHandles(CSignedMsgData
*msg_data
)
956 if (msg_data
->info
->cSignerInfo
)
958 msg_data
->signerHandles
=
959 CryptMemAlloc(msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
960 if (msg_data
->signerHandles
)
962 msg_data
->cSignerHandle
= msg_data
->info
->cSignerInfo
;
963 memset(msg_data
->signerHandles
, 0,
964 msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
968 msg_data
->cSignerHandle
= 0;
974 msg_data
->cSignerHandle
= 0;
975 msg_data
->signerHandles
= NULL
;
980 static void CSignedMsgData_CloseHandles(CSignedMsgData
*msg_data
)
984 for (i
= 0; i
< msg_data
->cSignerHandle
; i
++)
986 if (msg_data
->signerHandles
[i
].contentHash
)
987 CryptDestroyHash(msg_data
->signerHandles
[i
].contentHash
);
988 if (msg_data
->signerHandles
[i
].authAttrHash
)
989 CryptDestroyHash(msg_data
->signerHandles
[i
].authAttrHash
);
991 CryptMemFree(msg_data
->signerHandles
);
992 msg_data
->signerHandles
= NULL
;
993 msg_data
->cSignerHandle
= 0;
996 static BOOL
CSignedMsgData_UpdateHash(CSignedMsgData
*msg_data
,
997 const BYTE
*pbData
, DWORD cbData
)
1002 for (i
= 0; ret
&& i
< msg_data
->cSignerHandle
; i
++)
1003 ret
= CryptHashData(msg_data
->signerHandles
[i
].contentHash
, pbData
,
1008 static BOOL
CRYPT_AppendAttribute(CRYPT_ATTRIBUTES
*out
,
1009 const CRYPT_ATTRIBUTE
*in
)
1013 out
->rgAttr
= CryptMemRealloc(out
->rgAttr
,
1014 (out
->cAttr
+ 1) * sizeof(CRYPT_ATTRIBUTE
));
1017 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[out
->cAttr
], in
);
1024 static BOOL
CSignedMsgData_AppendMessageDigestAttribute(
1025 CSignedMsgData
*msg_data
, DWORD signerIndex
)
1029 CRYPT_HASH_BLOB hash
= { 0, NULL
}, encodedHash
= { 0, NULL
};
1030 char messageDigest
[] = szOID_RSA_messageDigest
;
1031 CRYPT_ATTRIBUTE messageDigestAttr
= { messageDigest
, 1, &encodedHash
};
1033 size
= sizeof(DWORD
);
1034 ret
= CryptGetHashParam(
1035 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHSIZE
,
1036 (LPBYTE
)&hash
.cbData
, &size
, 0);
1039 hash
.pbData
= CryptMemAlloc(hash
.cbData
);
1040 ret
= CryptGetHashParam(
1041 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHVAL
,
1042 hash
.pbData
, &hash
.cbData
, 0);
1045 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &hash
, CRYPT_ENCODE_ALLOC_FLAG
,
1046 NULL
, (LPBYTE
)&encodedHash
.pbData
, &encodedHash
.cbData
);
1049 ret
= CRYPT_AppendAttribute(
1050 &msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
,
1051 &messageDigestAttr
);
1052 LocalFree(encodedHash
.pbData
);
1055 CryptMemFree(hash
.pbData
);
1065 static BOOL
CSignedMsgData_UpdateAuthenticatedAttributes(
1066 CSignedMsgData
*msg_data
, SignOrVerify flag
)
1071 TRACE("(%p)\n", msg_data
);
1073 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1075 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1079 BYTE oid_rsa_data_encoded
[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
1080 0xf7,0x0d,0x01,0x07,0x01 };
1081 CRYPT_DATA_BLOB content
= { sizeof(oid_rsa_data_encoded
),
1082 oid_rsa_data_encoded
};
1083 char contentType
[] = szOID_RSA_contentType
;
1084 CRYPT_ATTRIBUTE contentTypeAttr
= { contentType
, 1, &content
};
1086 /* FIXME: does this depend on inner OID? */
1087 ret
= CRYPT_AppendAttribute(
1088 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
, &contentTypeAttr
);
1090 ret
= CSignedMsgData_AppendMessageDigestAttribute(msg_data
,
1095 LPBYTE encodedAttrs
;
1098 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, PKCS_ATTRIBUTES
,
1099 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
,
1100 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &encodedAttrs
, &size
);
1103 ret
= CryptHashData(
1104 msg_data
->signerHandles
[i
].authAttrHash
, encodedAttrs
,
1106 LocalFree(encodedAttrs
);
1111 TRACE("returning %d\n", ret
);
1115 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB
*hash
)
1120 for (i
= 0; i
< hash
->cbData
/ 2; i
++)
1122 tmp
= hash
->pbData
[hash
->cbData
- i
- 1];
1123 hash
->pbData
[hash
->cbData
- i
- 1] = hash
->pbData
[i
];
1124 hash
->pbData
[i
] = tmp
;
1128 static BOOL
CSignedMsgData_Sign(CSignedMsgData
*msg_data
)
1133 TRACE("(%p)\n", msg_data
);
1135 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1138 DWORD keySpec
= msg_data
->info
->signerKeySpec
[i
];
1141 keySpec
= AT_SIGNATURE
;
1142 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1143 hash
= msg_data
->signerHandles
[i
].authAttrHash
;
1145 hash
= msg_data
->signerHandles
[i
].contentHash
;
1146 ret
= CryptSignHashW(hash
, keySpec
, NULL
, 0, NULL
,
1147 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1150 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
=
1152 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1153 if (msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
)
1155 ret
= CryptSignHashW(hash
, keySpec
, NULL
, 0,
1156 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
,
1157 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1160 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
);
1169 static BOOL
CSignedMsgData_Update(CSignedMsgData
*msg_data
,
1170 const BYTE
*pbData
, DWORD cbData
, BOOL fFinal
, SignOrVerify flag
)
1172 BOOL ret
= CSignedMsgData_UpdateHash(msg_data
, pbData
, cbData
);
1176 ret
= CSignedMsgData_UpdateAuthenticatedAttributes(msg_data
, flag
);
1177 if (ret
&& flag
== Sign
)
1178 ret
= CSignedMsgData_Sign(msg_data
);
1183 typedef struct _CSignedEncodeMsg
1187 CRYPT_DATA_BLOB data
;
1188 CSignedMsgData msg_data
;
1191 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1193 CSignedEncodeMsg
*msg
= hCryptMsg
;
1196 CryptMemFree(msg
->innerOID
);
1197 CryptMemFree(msg
->data
.pbData
);
1198 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCertEncoded
,
1199 msg
->msg_data
.info
->rgCertEncoded
);
1200 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCrlEncoded
,
1201 msg
->msg_data
.info
->rgCrlEncoded
);
1202 for (i
= 0; i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1203 CSignerInfo_Free(&msg
->msg_data
.info
->rgSignerInfo
[i
]);
1204 CSignedMsgData_CloseHandles(&msg
->msg_data
);
1205 CryptMemFree(msg
->msg_data
.info
->signerKeySpec
);
1206 CryptMemFree(msg
->msg_data
.info
->rgSignerInfo
);
1207 CryptMemFree(msg
->msg_data
.info
);
1210 static BOOL
CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1211 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1213 CSignedEncodeMsg
*msg
= hCryptMsg
;
1216 switch (dwParamType
)
1218 case CMSG_CONTENT_PARAM
:
1220 CRYPT_CONTENT_INFO info
;
1222 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1223 &info
.Content
.cbData
);
1226 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1227 if (info
.Content
.pbData
)
1229 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1230 info
.Content
.pbData
, &info
.Content
.cbData
);
1233 char oid_rsa_signed
[] = szOID_RSA_signedData
;
1235 info
.pszObjId
= oid_rsa_signed
;
1236 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1237 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1239 CryptMemFree(info
.Content
.pbData
);
1246 case CMSG_BARE_CONTENT_PARAM
:
1248 CRYPT_SIGNED_INFO info
;
1249 BOOL freeContent
= FALSE
;
1251 info
= *msg
->msg_data
.info
;
1252 if (!msg
->innerOID
|| !strcmp(msg
->innerOID
, szOID_RSA_data
))
1254 char oid_rsa_data
[] = szOID_RSA_data
;
1256 /* Quirk: OID is only encoded messages if an update has happened */
1257 if (msg
->base
.state
!= MsgStateInit
)
1258 info
.content
.pszObjId
= oid_rsa_data
;
1260 info
.content
.pszObjId
= NULL
;
1261 if (msg
->data
.cbData
)
1263 CRYPT_DATA_BLOB blob
= { msg
->data
.cbData
, msg
->data
.pbData
};
1265 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1266 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
1267 &info
.content
.Content
.pbData
, &info
.content
.Content
.cbData
);
1272 info
.content
.Content
.cbData
= 0;
1273 info
.content
.Content
.pbData
= NULL
;
1279 info
.content
.pszObjId
= msg
->innerOID
;
1280 info
.content
.Content
.cbData
= msg
->data
.cbData
;
1281 info
.content
.Content
.pbData
= msg
->data
.pbData
;
1286 ret
= CRYPT_AsnEncodeCMSSignedInfo(&info
, pvData
, pcbData
);
1288 LocalFree(info
.content
.Content
.pbData
);
1292 case CMSG_COMPUTED_HASH_PARAM
:
1293 if (dwIndex
>= msg
->msg_data
.cSignerHandle
)
1294 SetLastError(CRYPT_E_INVALID_INDEX
);
1296 ret
= CryptGetHashParam(
1297 msg
->msg_data
.signerHandles
[dwIndex
].contentHash
, HP_HASHVAL
,
1298 pvData
, pcbData
, 0);
1300 case CMSG_ENCODED_SIGNER
:
1301 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1302 SetLastError(CRYPT_E_INVALID_INDEX
);
1304 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1305 CMS_SIGNER_INFO
, &msg
->msg_data
.info
->rgSignerInfo
[dwIndex
], 0,
1306 NULL
, pvData
, pcbData
);
1308 case CMSG_VERSION_PARAM
:
1309 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->msg_data
.info
->version
,
1310 sizeof(msg
->msg_data
.info
->version
));
1313 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1318 static BOOL
CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1319 DWORD cbData
, BOOL fFinal
)
1321 CSignedEncodeMsg
*msg
= hCryptMsg
;
1324 if (msg
->base
.state
== MsgStateFinalized
)
1325 SetLastError(CRYPT_E_MSG_ERROR
);
1326 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1328 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
, fFinal
,
1330 if (msg
->base
.streamed
)
1331 FIXME("streamed partial stub\n");
1332 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1337 SetLastError(CRYPT_E_MSG_ERROR
);
1342 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1343 if (msg
->data
.pbData
)
1345 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1346 msg
->data
.cbData
= cbData
;
1353 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
,
1355 msg
->base
.state
= MsgStateFinalized
;
1361 static HCRYPTMSG
CSignedEncodeMsg_Open(DWORD dwFlags
,
1362 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1363 PCMSG_STREAM_INFO pStreamInfo
)
1365 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1367 CSignedEncodeMsg
*msg
;
1369 if (info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO
) &&
1370 info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1372 SetLastError(E_INVALIDARG
);
1375 if (info
->cbSize
== sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
) &&
1376 info
->cAttrCertEncoded
)
1378 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1381 for (i
= 0; i
< info
->cSigners
; i
++)
1382 if (!CRYPT_IsValidSigner(&info
->rgSigners
[i
]))
1384 msg
= CryptMemAlloc(sizeof(CSignedEncodeMsg
));
1389 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1390 CSignedEncodeMsg_Close
, CSignedEncodeMsg_GetParam
,
1391 CSignedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1392 if (pszInnerContentObjID
)
1394 msg
->innerOID
= CryptMemAlloc(strlen(pszInnerContentObjID
) + 1);
1396 strcpy(msg
->innerOID
, pszInnerContentObjID
);
1401 msg
->innerOID
= NULL
;
1402 msg
->data
.cbData
= 0;
1403 msg
->data
.pbData
= NULL
;
1405 msg
->msg_data
.info
= CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO
));
1407 msg
->msg_data
.info
= NULL
;
1408 if (msg
->msg_data
.info
)
1410 memset(msg
->msg_data
.info
, 0, sizeof(CRYPT_SIGNED_INFO
));
1411 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V1
;
1419 msg
->msg_data
.info
->rgSignerInfo
=
1420 CryptMemAlloc(info
->cSigners
* sizeof(CMSG_CMS_SIGNER_INFO
));
1421 if (msg
->msg_data
.info
->rgSignerInfo
)
1423 msg
->msg_data
.info
->cSignerInfo
= info
->cSigners
;
1424 memset(msg
->msg_data
.info
->rgSignerInfo
, 0,
1425 msg
->msg_data
.info
->cSignerInfo
*
1426 sizeof(CMSG_CMS_SIGNER_INFO
));
1427 ret
= CSignedMsgData_AllocateHandles(&msg
->msg_data
);
1428 msg
->msg_data
.info
->signerKeySpec
= CryptMemAlloc(info
->cSigners
* sizeof(DWORD
));
1429 if (!msg
->msg_data
.info
->signerKeySpec
)
1431 for (i
= 0; ret
&& i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1433 if (info
->rgSigners
[i
].SignerId
.dwIdChoice
==
1434 CERT_ID_KEY_IDENTIFIER
)
1435 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V3
;
1436 ret
= CSignerInfo_Construct(
1437 &msg
->msg_data
.info
->rgSignerInfo
[i
],
1438 &info
->rgSigners
[i
]);
1441 ret
= CSignedMsgData_ConstructSignerHandles(
1442 &msg
->msg_data
, i
, &info
->rgSigners
[i
].hCryptProv
, &dwFlags
);
1443 if (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1444 CryptReleaseContext(info
->rgSigners
[i
].hCryptProv
,
1447 msg
->msg_data
.info
->signerKeySpec
[i
] =
1448 info
->rgSigners
[i
].dwKeySpec
;
1456 msg
->msg_data
.info
->cSignerInfo
= 0;
1457 msg
->msg_data
.signerHandles
= NULL
;
1458 msg
->msg_data
.cSignerHandle
= 0;
1462 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCertEncoded
,
1463 &msg
->msg_data
.info
->rgCertEncoded
, info
->cCertEncoded
,
1464 info
->rgCertEncoded
);
1466 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCrlEncoded
,
1467 &msg
->msg_data
.info
->rgCrlEncoded
, info
->cCrlEncoded
,
1468 info
->rgCrlEncoded
);
1471 CSignedEncodeMsg_Close(msg
);
1479 typedef struct _CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
1482 HCRYPTPROV_LEGACY hCryptProv
;
1483 CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm
;
1484 void *pvEncryptionAuxInfo
;
1486 PCERT_INFO
*rgpRecipientCert
;
1487 PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients
;
1489 PCERT_BLOB rgCertEncoded
;
1491 PCRL_BLOB rgCrlEncoded
;
1492 DWORD cAttrCertEncoded
;
1493 PCERT_BLOB rgAttrCertEncoded
;
1494 DWORD cUnprotectedAttr
;
1495 PCRYPT_ATTRIBUTE rgUnprotectedAttr
;
1496 } CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
;
1498 typedef struct _CEnvelopedEncodeMsg
1501 CRYPT_ALGORITHM_IDENTIFIER algo
;
1504 DWORD cRecipientInfo
;
1505 CMSG_KEY_TRANS_RECIPIENT_INFO
*recipientInfo
;
1506 CRYPT_DATA_BLOB data
;
1507 } CEnvelopedEncodeMsg
;
1509 static BOOL
CRYPT_ConstructAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
1510 const CRYPT_ALGORITHM_IDENTIFIER
*in
)
1512 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
1515 strcpy(out
->pszObjId
, in
->pszObjId
);
1516 return CRYPT_ConstructBlob(&out
->Parameters
, &in
->Parameters
);
1522 static BOOL
CRYPT_ConstructBitBlob(CRYPT_BIT_BLOB
*out
, const CRYPT_BIT_BLOB
*in
)
1524 out
->cbData
= in
->cbData
;
1525 out
->cUnusedBits
= in
->cUnusedBits
;
1528 out
->pbData
= CryptMemAlloc(out
->cbData
);
1530 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
1539 static BOOL
CRYPT_GenKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, ALG_ID algID
)
1541 static HCRYPTOIDFUNCSET set
= NULL
;
1542 PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY genKeyFunc
= NULL
;
1543 HCRYPTOIDFUNCADDR hFunc
;
1547 set
= CryptInitOIDFunctionSet(CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC
, 0);
1548 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1549 info
->ContentEncryptionAlgorithm
.pszObjId
, 0, (void **)&genKeyFunc
, &hFunc
);
1552 ret
= genKeyFunc(info
, 0, NULL
);
1553 CryptFreeOIDFunctionAddress(hFunc
, 0);
1556 ret
= CryptGenKey(info
->hCryptProv
, algID
, CRYPT_EXPORTABLE
,
1557 &info
->hContentEncryptKey
);
1561 static BOOL WINAPI
CRYPT_ExportKeyTrans(
1562 PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo
,
1563 PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo
,
1564 PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo
,
1565 DWORD dwFlags
, void *pvReserved
)
1567 CERT_PUBLIC_KEY_INFO keyInfo
;
1571 ret
= CRYPT_ConstructAlgorithmId(&keyInfo
.Algorithm
,
1572 &pKeyTransEncodeInfo
->KeyEncryptionAlgorithm
);
1574 ret
= CRYPT_ConstructBitBlob(&keyInfo
.PublicKey
,
1575 &pKeyTransEncodeInfo
->RecipientPublicKey
);
1577 ret
= CryptImportPublicKeyInfo(pKeyTransEncodeInfo
->hCryptProv
,
1578 X509_ASN_ENCODING
, &keyInfo
, &expKey
);
1583 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
, expKey
,
1584 SIMPLEBLOB
, 0, NULL
, &size
);
1589 keyBlob
= CryptMemAlloc(size
);
1592 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
,
1593 expKey
, SIMPLEBLOB
, 0, keyBlob
, &size
);
1596 DWORD head
= sizeof(BLOBHEADER
) + sizeof(ALG_ID
);
1598 pKeyTransEncryptInfo
->EncryptedKey
.pbData
=
1599 CryptMemAlloc(size
- head
);
1600 if (pKeyTransEncryptInfo
->EncryptedKey
.pbData
)
1604 pKeyTransEncryptInfo
->EncryptedKey
.cbData
= size
- head
;
1605 for (i
= size
- 1; i
>= head
; --i
, ++k
)
1606 pKeyTransEncryptInfo
->EncryptedKey
.pbData
[k
] =
1612 CryptMemFree(keyBlob
);
1617 CryptDestroyKey(expKey
);
1620 CryptMemFree(keyInfo
.PublicKey
.pbData
);
1621 CryptMemFree(keyInfo
.Algorithm
.pszObjId
);
1622 CryptMemFree(keyInfo
.Algorithm
.Parameters
.pbData
);
1626 static BOOL
CRYPT_ExportEncryptedKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, DWORD i
,
1627 CRYPT_DATA_BLOB
*key
)
1629 static HCRYPTOIDFUNCSET set
= NULL
;
1630 PFN_CMSG_EXPORT_KEY_TRANS exportKeyFunc
= NULL
;
1631 HCRYPTOIDFUNCADDR hFunc
= NULL
;
1632 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1633 info
->rgCmsRecipients
[i
].u
.pKeyTrans
;
1634 CMSG_KEY_TRANS_ENCRYPT_INFO encryptInfo
;
1637 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
1638 encryptInfo
.cbSize
= sizeof(encryptInfo
);
1639 encryptInfo
.dwRecipientIndex
= i
;
1640 ret
= CRYPT_ConstructAlgorithmId(&encryptInfo
.KeyEncryptionAlgorithm
,
1641 &encodeInfo
->KeyEncryptionAlgorithm
);
1644 set
= CryptInitOIDFunctionSet(CMSG_OID_EXPORT_KEY_TRANS_FUNC
, 0);
1645 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1646 encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
, 0, (void **)&exportKeyFunc
,
1649 exportKeyFunc
= CRYPT_ExportKeyTrans
;
1652 ret
= exportKeyFunc(info
, encodeInfo
, &encryptInfo
, 0, NULL
);
1655 key
->cbData
= encryptInfo
.EncryptedKey
.cbData
;
1656 key
->pbData
= encryptInfo
.EncryptedKey
.pbData
;
1660 CryptFreeOIDFunctionAddress(hFunc
, 0);
1662 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
);
1663 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.Parameters
.pbData
);
1667 static LPVOID WINAPI
mem_alloc(size_t size
)
1669 return HeapAlloc(GetProcessHeap(), 0, size
);
1672 static VOID WINAPI
mem_free(LPVOID pv
)
1674 HeapFree(GetProcessHeap(), 0, pv
);
1678 static BOOL
CContentEncryptInfo_Construct(CMSG_CONTENT_ENCRYPT_INFO
*info
,
1679 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*in
, HCRYPTPROV prov
)
1683 info
->cbSize
= sizeof(CMSG_CONTENT_ENCRYPT_INFO
);
1684 info
->hCryptProv
= prov
;
1685 ret
= CRYPT_ConstructAlgorithmId(&info
->ContentEncryptionAlgorithm
,
1686 &in
->ContentEncryptionAlgorithm
);
1687 info
->pvEncryptionAuxInfo
= in
->pvEncryptionAuxInfo
;
1688 info
->cRecipients
= in
->cRecipients
;
1691 info
->rgCmsRecipients
= CryptMemAlloc(in
->cRecipients
*
1692 sizeof(CMSG_RECIPIENT_ENCODE_INFO
));
1693 if (info
->rgCmsRecipients
)
1697 for (i
= 0; ret
&& i
< in
->cRecipients
; ++i
)
1699 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
;
1700 CERT_INFO
*cert
= in
->rgpRecipientCert
[i
];
1702 info
->rgCmsRecipients
[i
].dwRecipientChoice
=
1703 CMSG_KEY_TRANS_RECIPIENT
;
1704 encodeInfo
= CryptMemAlloc(sizeof(*encodeInfo
));
1705 info
->rgCmsRecipients
[i
].u
.pKeyTrans
= encodeInfo
;
1708 encodeInfo
->cbSize
= sizeof(*encodeInfo
);
1709 ret
= CRYPT_ConstructAlgorithmId(
1710 &encodeInfo
->KeyEncryptionAlgorithm
,
1711 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1712 encodeInfo
->pvKeyEncryptionAuxInfo
= NULL
;
1713 encodeInfo
->hCryptProv
= prov
;
1715 ret
= CRYPT_ConstructBitBlob(
1716 &encodeInfo
->RecipientPublicKey
,
1717 &cert
->SubjectPublicKeyInfo
.PublicKey
);
1719 ret
= CRYPT_ConstructBlob(
1720 &encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.Issuer
,
1723 ret
= CRYPT_ConstructBlob(
1724 &encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
,
1725 &cert
->SerialNumber
);
1734 info
->pfnAlloc
= mem_alloc
;
1735 info
->pfnFree
= mem_free
;
1739 static void CContentEncryptInfo_Free(CMSG_CONTENT_ENCRYPT_INFO
*info
)
1741 CryptMemFree(info
->ContentEncryptionAlgorithm
.pszObjId
);
1742 CryptMemFree(info
->ContentEncryptionAlgorithm
.Parameters
.pbData
);
1743 if (info
->rgCmsRecipients
)
1747 for (i
= 0; i
< info
->cRecipients
; ++i
)
1749 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1750 info
->rgCmsRecipients
[i
].u
.pKeyTrans
;
1752 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.pszObjId
);
1753 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1754 CryptMemFree(encodeInfo
->RecipientPublicKey
.pbData
);
1756 encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
1758 encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
1759 CryptMemFree(encodeInfo
);
1761 CryptMemFree(info
->rgCmsRecipients
);
1765 static BOOL
CRecipientInfo_Construct(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
,
1766 const CERT_INFO
*cert
, CRYPT_DATA_BLOB
*key
)
1770 info
->dwVersion
= CMSG_KEY_TRANS_PKCS_1_5_VERSION
;
1771 info
->RecipientId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
1772 ret
= CRYPT_ConstructBlob(&info
->RecipientId
.u
.IssuerSerialNumber
.Issuer
,
1775 ret
= CRYPT_ConstructBlob(
1776 &info
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
,
1777 &cert
->SerialNumber
);
1779 ret
= CRYPT_ConstructAlgorithmId(&info
->KeyEncryptionAlgorithm
,
1780 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1781 info
->EncryptedKey
.cbData
= key
->cbData
;
1782 info
->EncryptedKey
.pbData
= key
->pbData
;
1786 static void CRecipientInfo_Free(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
)
1788 CryptMemFree(info
->RecipientId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
1789 CryptMemFree(info
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
1790 CryptMemFree(info
->KeyEncryptionAlgorithm
.pszObjId
);
1791 CryptMemFree(info
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1792 CryptMemFree(info
->EncryptedKey
.pbData
);
1795 static void CEnvelopedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1797 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1799 CryptMemFree(msg
->algo
.pszObjId
);
1800 CryptMemFree(msg
->algo
.Parameters
.pbData
);
1801 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1802 CryptReleaseContext(msg
->prov
, 0);
1803 CryptDestroyKey(msg
->key
);
1804 if (msg
->recipientInfo
)
1808 for (i
= 0; i
< msg
->cRecipientInfo
; ++i
)
1809 CRecipientInfo_Free(&msg
->recipientInfo
[i
]);
1810 CryptMemFree(msg
->recipientInfo
);
1812 CryptMemFree(msg
->data
.pbData
);
1815 static BOOL
CEnvelopedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1816 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1818 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1821 switch (dwParamType
)
1823 case CMSG_BARE_CONTENT_PARAM
:
1824 if (msg
->base
.streamed
)
1825 SetLastError(E_INVALIDARG
);
1828 char oid_rsa_data
[] = szOID_RSA_data
;
1829 CRYPT_ENVELOPED_DATA envelopedData
= {
1830 CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION
, msg
->cRecipientInfo
,
1831 msg
->recipientInfo
, { oid_rsa_data
, {
1833 { msg
->algo
.Parameters
.cbData
, msg
->algo
.Parameters
.pbData
}
1835 { msg
->data
.cbData
, msg
->data
.pbData
}
1839 ret
= CRYPT_AsnEncodePKCSEnvelopedData(&envelopedData
, pvData
,
1843 case CMSG_CONTENT_PARAM
:
1845 CRYPT_CONTENT_INFO info
;
1847 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1848 &info
.Content
.cbData
);
1851 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1852 if (info
.Content
.pbData
)
1854 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1855 info
.Content
.pbData
, &info
.Content
.cbData
);
1858 char oid_rsa_enveloped
[] = szOID_RSA_envelopedData
;
1860 info
.pszObjId
= oid_rsa_enveloped
;
1861 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1862 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1864 CryptMemFree(info
.Content
.pbData
);
1872 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1877 static BOOL
CEnvelopedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1878 DWORD cbData
, BOOL fFinal
)
1880 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1883 if (msg
->base
.state
== MsgStateFinalized
)
1884 SetLastError(CRYPT_E_MSG_ERROR
);
1885 else if (msg
->base
.streamed
)
1887 FIXME("streamed stub\n");
1888 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1895 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1896 SetLastError(E_INVALIDARG
);
1898 SetLastError(CRYPT_E_MSG_ERROR
);
1904 DWORD dataLen
= cbData
;
1906 msg
->data
.cbData
= cbData
;
1907 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1908 if (msg
->data
.pbData
)
1910 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1911 ret
= CryptEncrypt(msg
->key
, 0, TRUE
, 0, msg
->data
.pbData
,
1912 &dataLen
, msg
->data
.cbData
);
1913 msg
->data
.cbData
= dataLen
;
1914 if (dataLen
> cbData
)
1916 msg
->data
.pbData
= CryptMemRealloc(msg
->data
.pbData
,
1918 if (msg
->data
.pbData
)
1921 ret
= CryptEncrypt(msg
->key
, 0, TRUE
, 0,
1922 msg
->data
.pbData
, &dataLen
, msg
->data
.cbData
);
1928 CryptMemFree(msg
->data
.pbData
);
1934 msg
->data
.cbData
= 0;
1935 msg
->data
.pbData
= NULL
;
1940 msg
->base
.state
= MsgStateFinalized
;
1946 static HCRYPTMSG
CEnvelopedEncodeMsg_Open(DWORD dwFlags
,
1947 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1948 PCMSG_STREAM_INFO pStreamInfo
)
1950 CEnvelopedEncodeMsg
*msg
;
1951 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1955 if (info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO
) &&
1956 info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1958 SetLastError(E_INVALIDARG
);
1961 if (info
->cbSize
== sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1962 FIXME("CMS fields unsupported\n");
1963 if (!(algID
= CertOIDToAlgId(info
->ContentEncryptionAlgorithm
.pszObjId
)))
1965 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
1968 if (info
->cRecipients
&& !info
->rgpRecipientCert
)
1970 SetLastError(E_INVALIDARG
);
1973 if (info
->hCryptProv
)
1974 prov
= info
->hCryptProv
;
1977 prov
= I_CryptGetDefaultCryptProv(0);
1978 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
1980 msg
= CryptMemAlloc(sizeof(CEnvelopedEncodeMsg
));
1983 CRYPT_DATA_BLOB encryptedKey
= { 0, NULL
};
1984 CMSG_CONTENT_ENCRYPT_INFO encryptInfo
;
1988 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1989 CEnvelopedEncodeMsg_Close
, CEnvelopedEncodeMsg_GetParam
,
1990 CEnvelopedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1991 ret
= CRYPT_ConstructAlgorithmId(&msg
->algo
,
1992 &info
->ContentEncryptionAlgorithm
);
1994 msg
->data
.cbData
= 0;
1995 msg
->data
.pbData
= NULL
;
1996 msg
->cRecipientInfo
= info
->cRecipients
;
1997 msg
->recipientInfo
= CryptMemAlloc(info
->cRecipients
*
1998 sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
));
1999 if (!msg
->recipientInfo
)
2001 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
2004 ret
= CContentEncryptInfo_Construct(&encryptInfo
, info
, prov
);
2007 ret
= CRYPT_GenKey(&encryptInfo
, algID
);
2009 msg
->key
= encryptInfo
.hContentEncryptKey
;
2012 for (i
= 0; ret
&& i
< msg
->cRecipientInfo
; ++i
)
2014 ret
= CRYPT_ExportEncryptedKey(&encryptInfo
, i
, &encryptedKey
);
2016 ret
= CRecipientInfo_Construct(&msg
->recipientInfo
[i
],
2017 info
->rgpRecipientCert
[i
], &encryptedKey
);
2019 CContentEncryptInfo_Free(&encryptInfo
);
2026 if (!msg
&& (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
))
2027 CryptReleaseContext(prov
, 0);
2031 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
2032 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
2033 PCMSG_STREAM_INFO pStreamInfo
)
2035 HCRYPTMSG msg
= NULL
;
2037 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
2038 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
2040 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
2042 SetLastError(E_INVALIDARG
);
2048 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2049 pszInnerContentObjID
, pStreamInfo
);
2052 msg
= CHashEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2053 pszInnerContentObjID
, pStreamInfo
);
2056 msg
= CSignedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2057 pszInnerContentObjID
, pStreamInfo
);
2059 case CMSG_ENVELOPED
:
2060 msg
= CEnvelopedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2061 pszInnerContentObjID
, pStreamInfo
);
2063 case CMSG_SIGNED_AND_ENVELOPED
:
2064 case CMSG_ENCRYPTED
:
2065 /* defined but invalid, fall through */
2067 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2072 typedef struct _CEnvelopedDecodeMsg
2074 CRYPT_ENVELOPED_DATA
*data
;
2075 HCRYPTPROV crypt_prov
;
2076 CRYPT_DATA_BLOB content
;
2078 } CEnvelopedDecodeMsg
;
2080 typedef struct _CDecodeMsg
2084 HCRYPTPROV crypt_prov
;
2087 CSignedMsgData signed_data
;
2088 CEnvelopedDecodeMsg enveloped_data
;
2090 CRYPT_DATA_BLOB msg_data
;
2091 CRYPT_DATA_BLOB detached_data
;
2092 CONTEXT_PROPERTY_LIST
*properties
;
2095 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg
)
2097 CDecodeMsg
*msg
= hCryptMsg
;
2099 if (msg
->crypt_prov
&& msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
2100 CryptReleaseContext(msg
->crypt_prov
, 0);
2105 CryptDestroyHash(msg
->u
.hash
);
2107 case CMSG_ENVELOPED
:
2108 if (msg
->u
.enveloped_data
.crypt_prov
)
2109 CryptReleaseContext(msg
->u
.enveloped_data
.crypt_prov
, 0);
2110 LocalFree(msg
->u
.enveloped_data
.data
);
2111 CryptMemFree(msg
->u
.enveloped_data
.content
.pbData
);
2114 if (msg
->u
.signed_data
.info
)
2116 LocalFree(msg
->u
.signed_data
.info
);
2117 CSignedMsgData_CloseHandles(&msg
->u
.signed_data
);
2121 CryptMemFree(msg
->msg_data
.pbData
);
2122 CryptMemFree(msg
->detached_data
.pbData
);
2123 ContextPropertyList_Free(msg
->properties
);
2126 static BOOL
CDecodeMsg_CopyData(CRYPT_DATA_BLOB
*blob
, const BYTE
*pbData
,
2134 blob
->pbData
= CryptMemRealloc(blob
->pbData
,
2135 blob
->cbData
+ cbData
);
2137 blob
->pbData
= CryptMemAlloc(cbData
);
2140 memcpy(blob
->pbData
+ blob
->cbData
, pbData
, cbData
);
2141 blob
->cbData
+= cbData
;
2149 static BOOL
CDecodeMsg_DecodeDataContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
)
2152 CRYPT_DATA_BLOB
*data
;
2155 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
2156 blob
->pbData
, blob
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &data
, &size
);
2159 ret
= ContextPropertyList_SetProperty(msg
->properties
,
2160 CMSG_CONTENT_PARAM
, data
->pbData
, data
->cbData
);
2166 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg
*msg
, DWORD param
,
2167 const CRYPT_ALGORITHM_IDENTIFIER
*id
)
2169 static const BYTE nullParams
[] = { ASN_NULL
, 0 };
2170 CRYPT_ALGORITHM_IDENTIFIER
*copy
;
2171 DWORD len
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
2173 /* Linearize algorithm id */
2174 len
+= strlen(id
->pszObjId
) + 1;
2175 len
+= id
->Parameters
.cbData
;
2176 copy
= CryptMemAlloc(len
);
2180 (LPSTR
)((BYTE
*)copy
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2181 strcpy(copy
->pszObjId
, id
->pszObjId
);
2182 copy
->Parameters
.pbData
= (BYTE
*)copy
->pszObjId
+ strlen(id
->pszObjId
)
2184 /* Trick: omit NULL parameters */
2185 if (id
->Parameters
.cbData
== sizeof(nullParams
) &&
2186 !memcmp(id
->Parameters
.pbData
, nullParams
, sizeof(nullParams
)))
2188 copy
->Parameters
.cbData
= 0;
2189 len
-= sizeof(nullParams
);
2192 copy
->Parameters
.cbData
= id
->Parameters
.cbData
;
2193 if (copy
->Parameters
.cbData
)
2194 memcpy(copy
->Parameters
.pbData
, id
->Parameters
.pbData
,
2195 id
->Parameters
.cbData
);
2196 ContextPropertyList_SetProperty(msg
->properties
, param
, (BYTE
*)copy
,
2202 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER
*id
)
2204 id
->pszObjId
= (LPSTR
)((BYTE
*)id
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2205 id
->Parameters
.pbData
= (BYTE
*)id
->pszObjId
+ strlen(id
->pszObjId
) + 1;
2208 static BOOL
CDecodeMsg_DecodeHashedContent(CDecodeMsg
*msg
,
2209 const CRYPT_DER_BLOB
*blob
)
2212 CRYPT_DIGESTED_DATA
*digestedData
;
2215 ret
= CRYPT_AsnDecodePKCSDigestedData(blob
->pbData
, blob
->cbData
,
2216 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_DIGESTED_DATA
*)&digestedData
,
2220 ContextPropertyList_SetProperty(msg
->properties
, CMSG_VERSION_PARAM
,
2221 (const BYTE
*)&digestedData
->version
, sizeof(digestedData
->version
));
2222 CDecodeMsg_SaveAlgorithmID(msg
, CMSG_HASH_ALGORITHM_PARAM
,
2223 &digestedData
->DigestAlgorithm
);
2224 ContextPropertyList_SetProperty(msg
->properties
,
2225 CMSG_INNER_CONTENT_TYPE_PARAM
,
2226 (const BYTE
*)digestedData
->ContentInfo
.pszObjId
,
2227 digestedData
->ContentInfo
.pszObjId
?
2228 strlen(digestedData
->ContentInfo
.pszObjId
) + 1 : 0);
2229 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
2231 if (digestedData
->ContentInfo
.Content
.cbData
)
2232 CDecodeMsg_DecodeDataContent(msg
,
2233 &digestedData
->ContentInfo
.Content
);
2235 ContextPropertyList_SetProperty(msg
->properties
,
2236 CMSG_CONTENT_PARAM
, NULL
, 0);
2238 ContextPropertyList_SetProperty(msg
->properties
, CMSG_HASH_DATA_PARAM
,
2239 digestedData
->hash
.pbData
, digestedData
->hash
.cbData
);
2240 LocalFree(digestedData
);
2245 static BOOL
CDecodeMsg_DecodeEnvelopedContent(CDecodeMsg
*msg
,
2246 const CRYPT_DER_BLOB
*blob
)
2249 CRYPT_ENVELOPED_DATA
*envelopedData
;
2252 ret
= CRYPT_AsnDecodePKCSEnvelopedData(blob
->pbData
, blob
->cbData
,
2253 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_ENVELOPED_DATA
*)&envelopedData
,
2256 msg
->u
.enveloped_data
.data
= envelopedData
;
2260 static BOOL
CDecodeMsg_DecodeSignedContent(CDecodeMsg
*msg
,
2261 const CRYPT_DER_BLOB
*blob
)
2264 CRYPT_SIGNED_INFO
*signedInfo
;
2267 ret
= CRYPT_AsnDecodeCMSSignedInfo(blob
->pbData
, blob
->cbData
,
2268 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_SIGNED_INFO
*)&signedInfo
,
2271 msg
->u
.signed_data
.info
= signedInfo
;
2275 /* Decodes the content in blob as the type given, and updates the value
2276 * (type, parameters, etc.) of msg based on what blob contains.
2277 * It doesn't just use msg's type, to allow a recursive call from an implicitly
2278 * typed message once the outer content info has been decoded.
2280 static BOOL
CDecodeMsg_DecodeContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
,
2288 if ((ret
= CDecodeMsg_DecodeDataContent(msg
, blob
)))
2289 msg
->type
= CMSG_DATA
;
2292 if ((ret
= CDecodeMsg_DecodeHashedContent(msg
, blob
)))
2293 msg
->type
= CMSG_HASHED
;
2295 case CMSG_ENVELOPED
:
2296 if ((ret
= CDecodeMsg_DecodeEnvelopedContent(msg
, blob
)))
2297 msg
->type
= CMSG_ENVELOPED
;
2300 if ((ret
= CDecodeMsg_DecodeSignedContent(msg
, blob
)))
2301 msg
->type
= CMSG_SIGNED
;
2305 CRYPT_CONTENT_INFO
*info
;
2308 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
,
2309 msg
->msg_data
.pbData
, msg
->msg_data
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
2310 NULL
, &info
, &size
);
2313 if (!strcmp(info
->pszObjId
, szOID_RSA_data
))
2314 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
, CMSG_DATA
);
2315 else if (!strcmp(info
->pszObjId
, szOID_RSA_digestedData
))
2316 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2318 else if (!strcmp(info
->pszObjId
, szOID_RSA_envelopedData
))
2319 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2321 else if (!strcmp(info
->pszObjId
, szOID_RSA_signedData
))
2322 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2326 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2336 static BOOL
CDecodeMsg_FinalizeHashedContent(CDecodeMsg
*msg
,
2337 CRYPT_DER_BLOB
*blob
)
2339 CRYPT_ALGORITHM_IDENTIFIER
*hashAlgoID
= NULL
;
2344 CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, NULL
, &size
);
2345 hashAlgoID
= CryptMemAlloc(size
);
2346 ret
= CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, hashAlgoID
,
2349 algID
= CertOIDToAlgId(hashAlgoID
->pszObjId
);
2351 if (!msg
->crypt_prov
)
2353 msg
->crypt_prov
= I_CryptGetDefaultCryptProv(algID
);
2354 if (msg
->crypt_prov
)
2355 msg
->base
.open_flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
2358 ret
= CryptCreateHash(msg
->crypt_prov
, algID
, 0, 0, &msg
->u
.hash
);
2361 CRYPT_DATA_BLOB content
;
2363 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2365 /* Unlike for non-detached messages, the data were never stored as
2366 * the content param, but were saved in msg->detached_data instead.
2368 content
.pbData
= msg
->detached_data
.pbData
;
2369 content
.cbData
= msg
->detached_data
.cbData
;
2372 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2373 CMSG_CONTENT_PARAM
, &content
);
2375 ret
= CryptHashData(msg
->u
.hash
, content
.pbData
, content
.cbData
, 0);
2377 CryptMemFree(hashAlgoID
);
2381 static BOOL
CDecodeMsg_FinalizeEnvelopedContent(CDecodeMsg
*msg
,
2382 CRYPT_DER_BLOB
*blob
)
2384 CRYPT_DATA_BLOB
*content
;
2386 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2387 content
= &msg
->detached_data
;
2390 &msg
->u
.enveloped_data
.data
->encryptedContentInfo
.encryptedContent
;
2392 return CRYPT_ConstructBlob(&msg
->u
.enveloped_data
.content
, content
);
2395 static BOOL
CDecodeMsg_FinalizeSignedContent(CDecodeMsg
*msg
,
2396 CRYPT_DER_BLOB
*blob
)
2401 ret
= CSignedMsgData_AllocateHandles(&msg
->u
.signed_data
);
2402 for (i
= 0; ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
2403 ret
= CSignedMsgData_ConstructSignerHandles(&msg
->u
.signed_data
, i
,
2404 &msg
->crypt_prov
, &msg
->base
.open_flags
);
2407 CRYPT_DATA_BLOB
*content
;
2409 /* Now that we have all the content, update the hash handles with
2410 * it. If the message is a detached message, the content is stored
2411 * in msg->detached_data rather than in the signed message's
2414 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2415 content
= &msg
->detached_data
;
2417 content
= &msg
->u
.signed_data
.info
->content
.Content
;
2418 if (content
->cbData
)
2420 /* If the message is not detached, have to decode the message's
2421 * content if the type is szOID_RSA_data.
2423 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) &&
2424 !strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2427 CRYPT_DATA_BLOB
*rsa_blob
;
2429 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
,
2430 X509_OCTET_STRING
, content
->pbData
, content
->cbData
,
2431 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &rsa_blob
, &size
);
2434 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2435 rsa_blob
->pbData
, rsa_blob
->cbData
, TRUE
, Verify
);
2436 LocalFree(rsa_blob
);
2440 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2441 content
->pbData
, content
->cbData
, TRUE
, Verify
);
2447 static BOOL
CDecodeMsg_FinalizeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
2454 ret
= CDecodeMsg_FinalizeHashedContent(msg
, blob
);
2456 case CMSG_ENVELOPED
:
2457 ret
= CDecodeMsg_FinalizeEnvelopedContent(msg
, blob
);
2460 ret
= CDecodeMsg_FinalizeSignedContent(msg
, blob
);
2468 static BOOL
CDecodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
2469 DWORD cbData
, BOOL fFinal
)
2471 CDecodeMsg
*msg
= hCryptMsg
;
2474 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
2476 if (msg
->base
.state
== MsgStateFinalized
)
2477 SetLastError(CRYPT_E_MSG_ERROR
);
2478 else if (msg
->base
.streamed
)
2480 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg
, pbData
,
2482 switch (msg
->base
.state
)
2485 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2488 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2489 msg
->base
.state
= MsgStateDataFinalized
;
2491 msg
->base
.state
= MsgStateFinalized
;
2494 msg
->base
.state
= MsgStateUpdated
;
2496 case MsgStateUpdated
:
2497 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2500 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2501 msg
->base
.state
= MsgStateDataFinalized
;
2503 msg
->base
.state
= MsgStateFinalized
;
2506 case MsgStateDataFinalized
:
2507 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2509 msg
->base
.state
= MsgStateFinalized
;
2512 SetLastError(CRYPT_E_MSG_ERROR
);
2519 SetLastError(CRYPT_E_MSG_ERROR
);
2522 switch (msg
->base
.state
)
2525 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2526 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2527 msg
->base
.state
= MsgStateDataFinalized
;
2529 msg
->base
.state
= MsgStateFinalized
;
2531 case MsgStateDataFinalized
:
2532 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2533 msg
->base
.state
= MsgStateFinalized
;
2536 SetLastError(CRYPT_E_MSG_ERROR
);
2540 if (ret
&& fFinal
&&
2541 ((msg
->base
.open_flags
& CMSG_DETACHED_FLAG
&& msg
->base
.state
==
2542 MsgStateDataFinalized
) ||
2543 (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->base
.state
==
2544 MsgStateFinalized
)))
2545 ret
= CDecodeMsg_DecodeContent(msg
, &msg
->msg_data
, msg
->type
);
2546 if (ret
&& msg
->base
.state
== MsgStateFinalized
)
2547 ret
= CDecodeMsg_FinalizeContent(msg
, &msg
->msg_data
);
2551 static BOOL
CDecodeHashMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2552 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2556 switch (dwParamType
)
2558 case CMSG_TYPE_PARAM
:
2559 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2561 case CMSG_HASH_ALGORITHM_PARAM
:
2563 CRYPT_DATA_BLOB blob
;
2565 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2569 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2571 CRYPT_FixUpAlgorithmID(pvData
);
2574 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2577 case CMSG_COMPUTED_HASH_PARAM
:
2578 ret
= CryptGetHashParam(msg
->u
.hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
2582 CRYPT_DATA_BLOB blob
;
2584 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2587 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2589 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2595 /* nextData is an in/out parameter - on input it's the memory location in
2596 * which a copy of in's data should be made, and on output it's the memory
2597 * location immediately after out's copy of in's data.
2599 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB
*out
,
2600 const CRYPT_DATA_BLOB
*in
, LPBYTE
*nextData
)
2602 out
->cbData
= in
->cbData
;
2605 out
->pbData
= *nextData
;
2606 memcpy(out
->pbData
, in
->pbData
, in
->cbData
);
2607 *nextData
+= in
->cbData
;
2611 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
2612 const CRYPT_ALGORITHM_IDENTIFIER
*in
, LPBYTE
*nextData
)
2616 out
->pszObjId
= (LPSTR
)*nextData
;
2617 strcpy(out
->pszObjId
, in
->pszObjId
);
2618 *nextData
+= strlen(out
->pszObjId
) + 1;
2620 CRYPT_CopyBlob(&out
->Parameters
, &in
->Parameters
, nextData
);
2623 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES
*out
,
2624 const CRYPT_ATTRIBUTES
*in
, LPBYTE
*nextData
)
2626 out
->cAttr
= in
->cAttr
;
2631 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2632 out
->rgAttr
= (CRYPT_ATTRIBUTE
*)*nextData
;
2633 *nextData
+= in
->cAttr
* sizeof(CRYPT_ATTRIBUTE
);
2634 for (i
= 0; i
< in
->cAttr
; i
++)
2636 if (in
->rgAttr
[i
].pszObjId
)
2638 out
->rgAttr
[i
].pszObjId
= (LPSTR
)*nextData
;
2639 strcpy(out
->rgAttr
[i
].pszObjId
, in
->rgAttr
[i
].pszObjId
);
2640 *nextData
+= strlen(in
->rgAttr
[i
].pszObjId
) + 1;
2642 if (in
->rgAttr
[i
].cValue
)
2646 out
->rgAttr
[i
].cValue
= in
->rgAttr
[i
].cValue
;
2647 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2648 out
->rgAttr
[i
].rgValue
= (PCRYPT_DATA_BLOB
)*nextData
;
2649 *nextData
+= in
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2650 for (j
= 0; j
< in
->rgAttr
[i
].cValue
; j
++)
2651 CRYPT_CopyBlob(&out
->rgAttr
[i
].rgValue
[j
],
2652 &in
->rgAttr
[i
].rgValue
[j
], nextData
);
2658 static DWORD
CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES
*attr
)
2660 DWORD size
= attr
->cAttr
* sizeof(CRYPT_ATTRIBUTE
), i
, j
;
2662 for (i
= 0; i
< attr
->cAttr
; i
++)
2664 if (attr
->rgAttr
[i
].pszObjId
)
2665 size
+= strlen(attr
->rgAttr
[i
].pszObjId
) + 1;
2667 size
= ALIGN_DWORD_PTR(size
);
2668 size
+= attr
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2669 for (j
= 0; j
< attr
->rgAttr
[i
].cValue
; j
++)
2670 size
+= attr
->rgAttr
[i
].rgValue
[j
].cbData
;
2672 /* align pointer again to be conservative */
2673 size
= ALIGN_DWORD_PTR(size
);
2677 static DWORD
CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB
*keyId
)
2679 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2682 CERT_RDN rdn
= { 1, &attr
};
2683 CERT_NAME_INFO name
= { 1, &rdn
};
2685 attr
.pszObjId
= oid_key_rdn
;
2686 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2687 attr
.Value
.cbData
= keyId
->cbData
;
2688 attr
.Value
.pbData
= keyId
->pbData
;
2689 if (CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, NULL
, &size
))
2690 size
++; /* Only include size of special zero serial number on success */
2694 static BOOL
CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB
*issuer
,
2695 CRYPT_INTEGER_BLOB
*serialNumber
, const CRYPT_DATA_BLOB
*keyId
, DWORD encodedLen
,
2698 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2700 CERT_RDN rdn
= { 1, &attr
};
2701 CERT_NAME_INFO name
= { 1, &rdn
};
2704 /* Encode special zero serial number */
2705 serialNumber
->cbData
= 1;
2706 serialNumber
->pbData
= *nextData
;
2710 issuer
->pbData
= *nextData
;
2711 attr
.pszObjId
= oid_key_rdn
;
2712 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2713 attr
.Value
.cbData
= keyId
->cbData
;
2714 attr
.Value
.pbData
= keyId
->pbData
;
2715 ret
= CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, *nextData
,
2719 *nextData
+= encodedLen
;
2720 issuer
->cbData
= encodedLen
;
2725 static BOOL
CRYPT_CopySignerInfo(void *pvData
, DWORD
*pcbData
,
2726 const CMSG_CMS_SIGNER_INFO
*in
)
2728 DWORD size
= sizeof(CMSG_SIGNER_INFO
), rdnSize
= 0;
2731 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2733 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2735 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2736 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2740 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2743 if (in
->HashAlgorithm
.pszObjId
)
2744 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2745 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2746 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2747 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2748 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2749 size
+= in
->EncryptedHash
.cbData
;
2751 size
= ALIGN_DWORD_PTR(size
);
2752 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2753 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2758 else if (*pcbData
< size
)
2760 SetLastError(ERROR_MORE_DATA
);
2765 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_SIGNER_INFO
);
2766 CMSG_SIGNER_INFO
*out
= pvData
;
2769 out
->dwVersion
= in
->dwVersion
;
2770 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2772 CRYPT_CopyBlob(&out
->Issuer
,
2773 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2774 CRYPT_CopyBlob(&out
->SerialNumber
,
2775 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2778 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2779 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2782 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2784 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2785 &in
->HashEncryptionAlgorithm
, &nextData
);
2786 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2787 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2788 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2789 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2793 TRACE("returning %d\n", ret
);
2797 static BOOL
CRYPT_CopyCMSSignerInfo(void *pvData
, DWORD
*pcbData
,
2798 const CMSG_CMS_SIGNER_INFO
*in
)
2800 DWORD size
= sizeof(CMSG_CMS_SIGNER_INFO
);
2803 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2805 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2807 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2808 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2811 size
+= in
->SignerId
.u
.KeyId
.cbData
;
2812 if (in
->HashAlgorithm
.pszObjId
)
2813 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2814 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2815 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2816 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2817 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2818 size
+= in
->EncryptedHash
.cbData
;
2820 size
= ALIGN_DWORD_PTR(size
);
2821 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2822 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2828 else if (*pcbData
< size
)
2831 SetLastError(ERROR_MORE_DATA
);
2836 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_CMS_SIGNER_INFO
);
2837 CMSG_CMS_SIGNER_INFO
*out
= pvData
;
2839 out
->dwVersion
= in
->dwVersion
;
2840 out
->SignerId
.dwIdChoice
= in
->SignerId
.dwIdChoice
;
2841 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2843 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
2844 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2845 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
2846 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2849 CRYPT_CopyBlob(&out
->SignerId
.u
.KeyId
, &in
->SignerId
.u
.KeyId
, &nextData
);
2850 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2852 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2853 &in
->HashEncryptionAlgorithm
, &nextData
);
2854 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2855 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2856 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2857 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2860 TRACE("returning %d\n", ret
);
2864 static BOOL
CRYPT_CopySignerCertInfo(void *pvData
, DWORD
*pcbData
,
2865 const CMSG_CMS_SIGNER_INFO
*in
)
2867 DWORD size
= sizeof(CERT_INFO
), rdnSize
= 0;
2870 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2872 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2874 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2875 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2879 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2887 else if (*pcbData
< size
)
2890 SetLastError(ERROR_MORE_DATA
);
2895 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2896 CERT_INFO
*out
= pvData
;
2898 memset(out
, 0, sizeof(CERT_INFO
));
2899 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2901 CRYPT_CopyBlob(&out
->Issuer
,
2902 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2903 CRYPT_CopyBlob(&out
->SerialNumber
,
2904 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2908 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2909 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2911 TRACE("returning %d\n", ret
);
2915 static BOOL
CRYPT_CopyRecipientInfo(void *pvData
, DWORD
*pcbData
,
2916 const CERT_ISSUER_SERIAL_NUMBER
*in
)
2918 DWORD size
= sizeof(CERT_INFO
);
2921 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2923 size
+= in
->SerialNumber
.cbData
;
2924 size
+= in
->Issuer
.cbData
;
2930 else if (*pcbData
< size
)
2933 SetLastError(ERROR_MORE_DATA
);
2938 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2939 CERT_INFO
*out
= pvData
;
2941 CRYPT_CopyBlob(&out
->SerialNumber
, &in
->SerialNumber
, &nextData
);
2942 CRYPT_CopyBlob(&out
->Issuer
, &in
->Issuer
, &nextData
);
2945 TRACE("returning %d\n", ret
);
2949 static BOOL
CDecodeEnvelopedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2950 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2954 switch (dwParamType
)
2956 case CMSG_TYPE_PARAM
:
2957 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2959 case CMSG_CONTENT_PARAM
:
2960 if (msg
->u
.enveloped_data
.data
)
2961 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2962 msg
->u
.enveloped_data
.content
.pbData
,
2963 msg
->u
.enveloped_data
.content
.cbData
);
2965 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2967 case CMSG_RECIPIENT_COUNT_PARAM
:
2968 if (msg
->u
.enveloped_data
.data
)
2969 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2970 &msg
->u
.enveloped_data
.data
->cRecipientInfo
, sizeof(DWORD
));
2972 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2974 case CMSG_RECIPIENT_INFO_PARAM
:
2975 if (msg
->u
.enveloped_data
.data
)
2977 if (dwIndex
< msg
->u
.enveloped_data
.data
->cRecipientInfo
)
2979 PCMSG_KEY_TRANS_RECIPIENT_INFO recipientInfo
=
2980 &msg
->u
.enveloped_data
.data
->rgRecipientInfo
[dwIndex
];
2982 ret
= CRYPT_CopyRecipientInfo(pvData
, pcbData
,
2983 &recipientInfo
->RecipientId
.u
.IssuerSerialNumber
);
2986 SetLastError(CRYPT_E_INVALID_INDEX
);
2989 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2992 FIXME("unimplemented for %d\n", dwParamType
);
2993 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2998 static BOOL
CRYPT_CopyAttr(void *pvData
, DWORD
*pcbData
, const CRYPT_ATTRIBUTES
*attr
)
3003 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, attr
);
3005 size
= CRYPT_SizeOfAttributes(attr
);
3011 else if (*pcbData
< size
)
3014 SetLastError(ERROR_MORE_DATA
);
3018 ret
= CRYPT_ConstructAttributes(pvData
, attr
);
3020 TRACE("returning %d\n", ret
);
3024 static BOOL
CDecodeSignedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
3025 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3029 switch (dwParamType
)
3031 case CMSG_TYPE_PARAM
:
3032 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
3034 case CMSG_CONTENT_PARAM
:
3035 if (msg
->u
.signed_data
.info
)
3037 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
3040 CRYPT_DATA_BLOB
*blob
;
3043 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
3044 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
3045 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
3046 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &blob
, &size
);
3049 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
->pbData
,
3055 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3056 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
3057 msg
->u
.signed_data
.info
->content
.Content
.cbData
);
3060 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3062 case CMSG_INNER_CONTENT_TYPE_PARAM
:
3063 if (msg
->u
.signed_data
.info
)
3064 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3065 msg
->u
.signed_data
.info
->content
.pszObjId
,
3066 strlen(msg
->u
.signed_data
.info
->content
.pszObjId
) + 1);
3068 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3070 case CMSG_SIGNER_COUNT_PARAM
:
3071 if (msg
->u
.signed_data
.info
)
3072 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3073 &msg
->u
.signed_data
.info
->cSignerInfo
, sizeof(DWORD
));
3075 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3077 case CMSG_SIGNER_INFO_PARAM
:
3078 if (msg
->u
.signed_data
.info
)
3080 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3081 SetLastError(CRYPT_E_INVALID_INDEX
);
3083 ret
= CRYPT_CopySignerInfo(pvData
, pcbData
,
3084 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3087 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3089 case CMSG_SIGNER_CERT_INFO_PARAM
:
3090 if (msg
->u
.signed_data
.info
)
3092 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3093 SetLastError(CRYPT_E_INVALID_INDEX
);
3095 ret
= CRYPT_CopySignerCertInfo(pvData
, pcbData
,
3096 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3099 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3101 case CMSG_CERT_COUNT_PARAM
:
3102 if (msg
->u
.signed_data
.info
)
3103 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3104 &msg
->u
.signed_data
.info
->cCertEncoded
, sizeof(DWORD
));
3106 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3108 case CMSG_CERT_PARAM
:
3109 if (msg
->u
.signed_data
.info
)
3111 if (dwIndex
>= msg
->u
.signed_data
.info
->cCertEncoded
)
3112 SetLastError(CRYPT_E_INVALID_INDEX
);
3114 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3115 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].pbData
,
3116 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].cbData
);
3119 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3121 case CMSG_CRL_COUNT_PARAM
:
3122 if (msg
->u
.signed_data
.info
)
3123 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3124 &msg
->u
.signed_data
.info
->cCrlEncoded
, sizeof(DWORD
));
3126 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3128 case CMSG_CRL_PARAM
:
3129 if (msg
->u
.signed_data
.info
)
3131 if (dwIndex
>= msg
->u
.signed_data
.info
->cCrlEncoded
)
3132 SetLastError(CRYPT_E_INVALID_INDEX
);
3134 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3135 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].pbData
,
3136 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].cbData
);
3139 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3141 case CMSG_COMPUTED_HASH_PARAM
:
3142 if (msg
->u
.signed_data
.info
)
3144 if (dwIndex
>= msg
->u
.signed_data
.cSignerHandle
)
3145 SetLastError(CRYPT_E_INVALID_INDEX
);
3147 ret
= CryptGetHashParam(
3148 msg
->u
.signed_data
.signerHandles
[dwIndex
].contentHash
,
3149 HP_HASHVAL
, pvData
, pcbData
, 0);
3152 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3154 case CMSG_ENCODED_SIGNER
:
3155 if (msg
->u
.signed_data
.info
)
3157 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3158 SetLastError(CRYPT_E_INVALID_INDEX
);
3160 ret
= CryptEncodeObjectEx(
3161 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, CMS_SIGNER_INFO
,
3162 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
], 0, NULL
,
3166 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3168 case CMSG_ATTR_CERT_COUNT_PARAM
:
3169 if (msg
->u
.signed_data
.info
)
3171 DWORD attrCertCount
= 0;
3173 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3174 &attrCertCount
, sizeof(DWORD
));
3177 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3179 case CMSG_ATTR_CERT_PARAM
:
3180 if (msg
->u
.signed_data
.info
)
3181 SetLastError(CRYPT_E_INVALID_INDEX
);
3183 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3185 case CMSG_CMS_SIGNER_INFO_PARAM
:
3186 if (msg
->u
.signed_data
.info
)
3188 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3189 SetLastError(CRYPT_E_INVALID_INDEX
);
3191 ret
= CRYPT_CopyCMSSignerInfo(pvData
, pcbData
,
3192 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3195 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3197 case CMSG_SIGNER_UNAUTH_ATTR_PARAM
:
3198 if (msg
->u
.signed_data
.info
)
3200 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3201 SetLastError(CRYPT_E_INVALID_INDEX
);
3203 ret
= CRYPT_CopyAttr(pvData
, pcbData
,
3204 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
].UnauthAttrs
);
3207 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3210 FIXME("unimplemented for %d\n", dwParamType
);
3211 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3216 static BOOL
CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
3217 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3219 CDecodeMsg
*msg
= hCryptMsg
;
3225 ret
= CDecodeHashMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3228 case CMSG_ENVELOPED
:
3229 ret
= CDecodeEnvelopedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3233 ret
= CDecodeSignedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3237 switch (dwParamType
)
3239 case CMSG_TYPE_PARAM
:
3240 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
,
3245 CRYPT_DATA_BLOB blob
;
3247 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
3250 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
,
3253 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3260 static BOOL
CDecodeHashMsg_VerifyHash(CDecodeMsg
*msg
)
3263 CRYPT_DATA_BLOB hashBlob
;
3265 ret
= ContextPropertyList_FindProperty(msg
->properties
,
3266 CMSG_HASH_DATA_PARAM
, &hashBlob
);
3269 DWORD computedHashSize
= 0;
3271 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
,
3273 if (hashBlob
.cbData
== computedHashSize
)
3275 LPBYTE computedHash
= CryptMemAlloc(computedHashSize
);
3279 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
3280 computedHash
, &computedHashSize
);
3283 if (memcmp(hashBlob
.pbData
, computedHash
, hashBlob
.cbData
))
3285 SetLastError(CRYPT_E_HASH_VALUE
);
3289 CryptMemFree(computedHash
);
3293 SetLastError(ERROR_OUTOFMEMORY
);
3299 SetLastError(CRYPT_E_HASH_VALUE
);
3306 static BOOL
CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg
*msg
,
3307 HCRYPTPROV prov
, DWORD signerIndex
, PCERT_PUBLIC_KEY_INFO keyInfo
)
3313 prov
= msg
->crypt_prov
;
3314 ret
= CryptImportPublicKeyInfo(prov
, X509_ASN_ENCODING
, keyInfo
, &key
);
3318 CRYPT_HASH_BLOB reversedHash
;
3320 if (msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
)
3321 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].authAttrHash
;
3323 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].contentHash
;
3324 ret
= CRYPT_ConstructBlob(&reversedHash
,
3325 &msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].EncryptedHash
);
3328 CRYPT_ReverseBytes(&reversedHash
);
3329 ret
= CryptVerifySignatureW(hash
, reversedHash
.pbData
,
3330 reversedHash
.cbData
, key
, NULL
, 0);
3331 CryptMemFree(reversedHash
.pbData
);
3333 CryptDestroyKey(key
);
3338 static BOOL
CDecodeSignedMsg_VerifySignature(CDecodeMsg
*msg
, PCERT_INFO info
)
3343 if (!msg
->u
.signed_data
.signerHandles
)
3345 SetLastError(NTE_BAD_SIGNATURE
);
3348 for (i
= 0; !ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
3350 PCMSG_CMS_SIGNER_INFO signerInfo
=
3351 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
];
3353 if (signerInfo
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
3355 ret
= CertCompareCertificateName(X509_ASN_ENCODING
,
3356 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
3360 ret
= CertCompareIntegerBlob(
3361 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
3362 &info
->SerialNumber
);
3369 FIXME("signer %d: unimplemented for key id\n", i
);
3373 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, 0, i
,
3374 &info
->SubjectPublicKeyInfo
);
3376 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3381 static BOOL
CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg
*msg
,
3382 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para
)
3386 if (para
->cbSize
!= sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
))
3387 SetLastError(ERROR_INVALID_PARAMETER
);
3388 else if (para
->dwSignerIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3389 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3390 else if (!msg
->u
.signed_data
.signerHandles
)
3391 SetLastError(NTE_BAD_SIGNATURE
);
3394 switch (para
->dwSignerType
)
3396 case CMSG_VERIFY_SIGNER_PUBKEY
:
3397 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
,
3398 para
->hCryptProv
, para
->dwSignerIndex
, para
->pvSigner
);
3400 case CMSG_VERIFY_SIGNER_CERT
:
3402 PCCERT_CONTEXT cert
= para
->pvSigner
;
3404 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, para
->hCryptProv
,
3405 para
->dwSignerIndex
, &cert
->pCertInfo
->SubjectPublicKeyInfo
);
3409 FIXME("unimplemented for signer type %d\n", para
->dwSignerType
);
3410 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3416 static BOOL WINAPI
CRYPT_ImportKeyTrans(
3417 PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm
,
3418 PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara
, DWORD dwFlags
,
3419 void *pvReserved
, HCRYPTKEY
*phContentEncryptKey
)
3424 ret
= CryptGetUserKey(pKeyTransDecryptPara
->hCryptProv
,
3425 pKeyTransDecryptPara
->dwKeySpec
? pKeyTransDecryptPara
->dwKeySpec
:
3426 AT_KEYEXCHANGE
, &key
);
3429 CMSG_KEY_TRANS_RECIPIENT_INFO
*info
=
3430 &pKeyTransDecryptPara
->pKeyTrans
[pKeyTransDecryptPara
->dwRecipientIndex
];
3431 CRYPT_DATA_BLOB
*encryptedKey
= &info
->EncryptedKey
;
3432 DWORD size
= encryptedKey
->cbData
+ sizeof(BLOBHEADER
) + sizeof(ALG_ID
);
3433 BYTE
*keyBlob
= CryptMemAlloc(size
);
3437 DWORD i
, k
= size
- 1;
3438 BLOBHEADER
*blobHeader
= (BLOBHEADER
*)keyBlob
;
3439 ALG_ID
*algID
= (ALG_ID
*)(keyBlob
+ sizeof(BLOBHEADER
));
3441 blobHeader
->bType
= SIMPLEBLOB
;
3442 blobHeader
->bVersion
= CUR_BLOB_VERSION
;
3443 blobHeader
->reserved
= 0;
3444 blobHeader
->aiKeyAlg
= CertOIDToAlgId(
3445 pContentEncryptionAlgorithm
->pszObjId
);
3446 *algID
= CertOIDToAlgId(info
->KeyEncryptionAlgorithm
.pszObjId
);
3447 for (i
= 0; i
< encryptedKey
->cbData
; ++i
, --k
)
3448 keyBlob
[k
] = encryptedKey
->pbData
[i
];
3450 ret
= CryptImportKey(pKeyTransDecryptPara
->hCryptProv
, keyBlob
,
3451 size
, key
, 0, phContentEncryptKey
);
3452 CryptMemFree(keyBlob
);
3456 CryptDestroyKey(key
);
3461 static BOOL
CRYPT_ImportEncryptedKey(PCRYPT_ALGORITHM_IDENTIFIER contEncrAlg
,
3462 PCMSG_CTRL_DECRYPT_PARA para
, PCMSG_KEY_TRANS_RECIPIENT_INFO info
,
3465 static HCRYPTOIDFUNCSET set
= NULL
;
3466 PFN_CMSG_IMPORT_KEY_TRANS importKeyFunc
= NULL
;
3467 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3468 CMSG_CTRL_KEY_TRANS_DECRYPT_PARA decryptPara
;
3471 memset(&decryptPara
, 0, sizeof(decryptPara
));
3472 decryptPara
.cbSize
= sizeof(decryptPara
);
3473 decryptPara
.hCryptProv
= para
->hCryptProv
;
3474 decryptPara
.dwKeySpec
= para
->dwKeySpec
;
3475 decryptPara
.pKeyTrans
= info
;
3476 decryptPara
.dwRecipientIndex
= para
->dwRecipientIndex
;
3479 set
= CryptInitOIDFunctionSet(CMSG_OID_IMPORT_KEY_TRANS_FUNC
, 0);
3480 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
, contEncrAlg
->pszObjId
, 0,
3481 (void **)&importKeyFunc
, &hFunc
);
3483 importKeyFunc
= CRYPT_ImportKeyTrans
;
3484 ret
= importKeyFunc(contEncrAlg
, &decryptPara
, 0, NULL
, key
);
3486 CryptFreeOIDFunctionAddress(hFunc
, 0);
3490 static BOOL
CDecodeEnvelopedMsg_CrtlDecrypt(CDecodeMsg
*msg
,
3491 PCMSG_CTRL_DECRYPT_PARA para
)
3494 CEnvelopedDecodeMsg
*enveloped_data
= &msg
->u
.enveloped_data
;
3495 CRYPT_ENVELOPED_DATA
*data
= enveloped_data
->data
;
3497 if (para
->cbSize
!= sizeof(CMSG_CTRL_DECRYPT_PARA
))
3498 SetLastError(E_INVALIDARG
);
3500 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3501 else if (para
->dwRecipientIndex
>= data
->cRecipientInfo
)
3502 SetLastError(CRYPT_E_INVALID_INDEX
);
3503 else if (enveloped_data
->decrypted
)
3504 SetLastError(CRYPT_E_ALREADY_DECRYPTED
);
3505 else if (!para
->hCryptProv
)
3506 SetLastError(ERROR_INVALID_PARAMETER
);
3507 else if (enveloped_data
->content
.cbData
)
3511 ret
= CRYPT_ImportEncryptedKey(
3512 &data
->encryptedContentInfo
.contentEncryptionAlgorithm
, para
,
3513 data
->rgRecipientInfo
, &key
);
3516 ret
= CryptDecrypt(key
, 0, TRUE
, 0, enveloped_data
->content
.pbData
,
3517 &enveloped_data
->content
.cbData
);
3518 CryptDestroyKey(key
);
3524 enveloped_data
->decrypted
= TRUE
;
3528 static BOOL
CDecodeMsg_Control(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3529 DWORD dwCtrlType
, const void *pvCtrlPara
)
3531 CDecodeMsg
*msg
= hCryptMsg
;
3536 case CMSG_CTRL_VERIFY_SIGNATURE
:
3540 ret
= CDecodeSignedMsg_VerifySignature(msg
, (PCERT_INFO
)pvCtrlPara
);
3543 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3546 case CMSG_CTRL_DECRYPT
:
3549 case CMSG_ENVELOPED
:
3550 ret
= CDecodeEnvelopedMsg_CrtlDecrypt(msg
,
3551 (PCMSG_CTRL_DECRYPT_PARA
)pvCtrlPara
);
3552 if (ret
&& (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
))
3553 msg
->u
.enveloped_data
.crypt_prov
=
3554 ((PCMSG_CTRL_DECRYPT_PARA
)pvCtrlPara
)->hCryptProv
;
3557 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3560 case CMSG_CTRL_VERIFY_HASH
:
3564 ret
= CDecodeHashMsg_VerifyHash(msg
);
3567 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3570 case CMSG_CTRL_VERIFY_SIGNATURE_EX
:
3574 ret
= CDecodeSignedMsg_VerifySignatureEx(msg
,
3575 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
)pvCtrlPara
);
3578 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3582 SetLastError(CRYPT_E_CONTROL_TYPE
);
3587 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
3588 DWORD dwMsgType
, HCRYPTPROV_LEGACY hCryptProv
, PCERT_INFO pRecipientInfo
,
3589 PCMSG_STREAM_INFO pStreamInfo
)
3593 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType
,
3594 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
3596 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
3598 SetLastError(E_INVALIDARG
);
3601 msg
= CryptMemAlloc(sizeof(CDecodeMsg
));
3604 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
3605 CDecodeMsg_Close
, CDecodeMsg_GetParam
, CDecodeMsg_Update
,
3606 CDecodeMsg_Control
);
3607 msg
->type
= dwMsgType
;
3608 msg
->crypt_prov
= hCryptProv
;
3609 memset(&msg
->u
, 0, sizeof(msg
->u
));
3610 msg
->msg_data
.cbData
= 0;
3611 msg
->msg_data
.pbData
= NULL
;
3612 msg
->detached_data
.cbData
= 0;
3613 msg
->detached_data
.pbData
= NULL
;
3614 msg
->properties
= ContextPropertyList_Create();
3619 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
3621 TRACE("(%p)\n", hCryptMsg
);
3625 CryptMsgBase
*msg
= hCryptMsg
;
3627 InterlockedIncrement(&msg
->ref
);
3632 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
3634 TRACE("(%p)\n", hCryptMsg
);
3638 CryptMsgBase
*msg
= hCryptMsg
;
3640 if (InterlockedDecrement(&msg
->ref
) == 0)
3642 TRACE("freeing %p\n", msg
);
3651 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
3652 DWORD cbData
, BOOL fFinal
)
3654 CryptMsgBase
*msg
= hCryptMsg
;
3656 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
3658 return msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
3661 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
3662 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3664 CryptMsgBase
*msg
= hCryptMsg
;
3666 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
3668 return msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);
3671 BOOL WINAPI
CryptMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3672 DWORD dwCtrlType
, const void *pvCtrlPara
)
3674 CryptMsgBase
*msg
= hCryptMsg
;
3676 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
,
3678 return msg
->control(hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
3681 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
3682 DWORD dwSignerIndex
)
3684 CERT_INFO
*certInfo
= NULL
;
3687 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
3690 certInfo
= CryptMemAlloc(size
);
3693 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
3694 dwSignerIndex
, certInfo
, &size
))
3696 CryptMemFree(certInfo
);
3704 BOOL WINAPI
CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg
, DWORD cSignerStore
,
3705 HCERTSTORE
*rghSignerStore
, DWORD dwFlags
, PCCERT_CONTEXT
*ppSigner
,
3706 DWORD
*pdwSignerIndex
)
3709 DWORD i
, signerIndex
= 0;
3710 PCCERT_CONTEXT signerCert
= NULL
;
3713 TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg
, cSignerStore
,
3714 rghSignerStore
, dwFlags
, ppSigner
, pdwSignerIndex
);
3716 /* Clear output parameters */
3719 if (pdwSignerIndex
&& !(dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
))
3720 *pdwSignerIndex
= 0;
3722 /* Create store to search for signer certificates */
3723 store
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
3724 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
3725 if (!(dwFlags
& CMSG_TRUSTED_SIGNER_FLAG
))
3727 HCERTSTORE msgStore
= CertOpenStore(CERT_STORE_PROV_MSG
, 0, 0, 0,
3730 CertAddStoreToCollection(store
, msgStore
, 0, 0);
3731 CertCloseStore(msgStore
, 0);
3733 for (i
= 0; i
< cSignerStore
; i
++)
3734 CertAddStoreToCollection(store
, rghSignerStore
[i
], 0, 0);
3736 /* Find signer cert */
3737 if (dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
)
3739 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3744 signerIndex
= *pdwSignerIndex
;
3745 signerCert
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
,
3746 0, CERT_FIND_SUBJECT_CERT
, signer
, NULL
);
3747 CryptMemFree(signer
);
3752 DWORD count
, size
= sizeof(count
);
3754 if (CryptMsgGetParam(hCryptMsg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
,
3757 for (i
= 0; !signerCert
&& i
< count
; i
++)
3759 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3764 signerCert
= CertFindCertificateInStore(store
,
3765 X509_ASN_ENCODING
, 0, CERT_FIND_SUBJECT_CERT
, signer
,
3769 CryptMemFree(signer
);
3774 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER
);
3778 if (!(dwFlags
& CMSG_SIGNER_ONLY_FLAG
))
3779 ret
= CryptMsgControl(hCryptMsg
, 0, CMSG_CTRL_VERIFY_SIGNATURE
,
3780 signerCert
->pCertInfo
);
3786 *ppSigner
= CertDuplicateCertificateContext(signerCert
);
3788 *pdwSignerIndex
= signerIndex
;
3790 CertFreeCertificateContext(signerCert
);
3793 CertCloseStore(store
, 0);
3797 BOOL WINAPI
CryptMsgVerifyCountersignatureEncoded(HCRYPTPROV_LEGACY hCryptProv
,
3798 DWORD dwEncodingType
, BYTE
*pbSignerInfo
, DWORD cbSignerInfo
,
3799 PBYTE pbSignerInfoCountersignature
, DWORD cbSignerInfoCountersignature
,
3800 CERT_INFO
*pciCountersigner
)
3802 FIXME("(%08lx, %08x, %p, %d, %p, %d, %p): stub\n", hCryptProv
,
3803 dwEncodingType
, pbSignerInfo
, cbSignerInfo
, pbSignerInfoCountersignature
,
3804 cbSignerInfoCountersignature
, pciCountersigner
);
3808 BOOL WINAPI
CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv
,
3809 DWORD dwEncodingType
, PBYTE pbSignerInfo
, DWORD cbSignerInfo
,
3810 PBYTE pbSignerInfoCountersignature
, DWORD cbSignerInfoCountersignature
,
3811 DWORD dwSignerType
, void *pvSigner
, DWORD dwFlags
, void *pvReserved
)
3813 FIXME("(%08lx, %08x, %p, %d, %p, %d, %d, %p, %08x, %p): stub\n", hCryptProv
,
3814 dwEncodingType
, pbSignerInfo
, cbSignerInfo
, pbSignerInfoCountersignature
,
3815 cbSignerInfoCountersignature
, dwSignerType
, pvSigner
, dwFlags
, pvReserved
);
3819 BOOL WINAPI
CryptMsgEncodeAndSignCTL(DWORD dwMsgEncodingType
,
3820 PCTL_INFO pCtlInfo
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3821 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3827 TRACE("(%08x, %p, %p, %08x, %p, %p)\n", dwMsgEncodingType
, pCtlInfo
,
3828 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3832 FIXME("unimplemented for flags %08x\n", dwFlags
);
3835 if ((ret
= CryptEncodeObjectEx(dwMsgEncodingType
, PKCS_CTL
, pCtlInfo
,
3836 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &pbCtlContent
, &cbCtlContent
)))
3838 ret
= CryptMsgSignCTL(dwMsgEncodingType
, pbCtlContent
, cbCtlContent
,
3839 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3840 LocalFree(pbCtlContent
);
3845 BOOL WINAPI
CryptMsgSignCTL(DWORD dwMsgEncodingType
, BYTE
*pbCtlContent
,
3846 DWORD cbCtlContent
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3847 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3849 static char oid_ctl
[] = szOID_CTL
;
3853 TRACE("(%08x, %p, %d, %p, %08x, %p, %p)\n", dwMsgEncodingType
,
3854 pbCtlContent
, cbCtlContent
, pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3858 FIXME("unimplemented for flags %08x\n", dwFlags
);
3861 msg
= CryptMsgOpenToEncode(dwMsgEncodingType
, 0, CMSG_SIGNED
, pSignInfo
,
3865 ret
= CryptMsgUpdate(msg
, pbCtlContent
, cbCtlContent
, TRUE
);
3867 ret
= CryptMsgGetParam(msg
, CMSG_CONTENT_PARAM
, 0, pbEncoded
,