2 * Copyright 2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/port.h"
23 #define NONAMELESSUNION
29 #include "wine/debug.h"
30 #include "wine/exception.h"
31 #include "crypt32_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
35 /* Called when a message's ref count reaches zero. Free any message-specific
38 typedef void (*CryptMsgCloseFunc
)(HCRYPTMSG msg
);
40 typedef BOOL (*CryptMsgGetParamFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
41 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
);
43 typedef BOOL (*CryptMsgUpdateFunc
)(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
44 DWORD cbData
, BOOL fFinal
);
46 typedef BOOL (*CryptMsgControlFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
47 DWORD dwCtrlType
, const void *pvCtrlPara
);
49 static BOOL
CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
50 DWORD dwCtrlType
, const void *pvCtrlPara
)
52 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
53 SetLastError(E_INVALIDARG
);
57 typedef enum _CryptMsgState
{
60 MsgStateDataFinalized
,
64 typedef struct _CryptMsgBase
69 CMSG_STREAM_INFO stream_info
;
71 CryptMsgCloseFunc close
;
72 CryptMsgUpdateFunc update
;
73 CryptMsgGetParamFunc get_param
;
74 CryptMsgControlFunc control
;
77 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
78 PCMSG_STREAM_INFO pStreamInfo
, CryptMsgCloseFunc close
,
79 CryptMsgGetParamFunc get_param
, CryptMsgUpdateFunc update
,
80 CryptMsgControlFunc control
)
83 msg
->open_flags
= dwFlags
;
87 msg
->stream_info
= *pStreamInfo
;
91 msg
->streamed
= FALSE
;
92 memset(&msg
->stream_info
, 0, sizeof(msg
->stream_info
));
95 msg
->get_param
= get_param
;
97 msg
->control
= control
;
98 msg
->state
= MsgStateInit
;
101 typedef struct _CDataEncodeMsg
104 DWORD bare_content_len
;
108 static const BYTE empty_data_content
[] = { 0x04,0x00 };
110 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
112 CDataEncodeMsg
*msg
= hCryptMsg
;
114 if (msg
->bare_content
!= empty_data_content
)
115 LocalFree(msg
->bare_content
);
118 static BOOL WINAPI
CRYPT_EncodeContentLength(DWORD dwCertEncodingType
,
119 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
120 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
122 DWORD dataLen
= *(DWORD
*)pvStructInfo
;
126 /* Trick: report bytes needed based on total message length, even though
127 * the message isn't available yet. The caller will use the length
128 * reported here to encode its length.
130 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
132 *pcbEncoded
= 1 + lenBytes
+ dataLen
;
135 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
136 pcbEncoded
, 1 + lenBytes
)))
138 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
139 pbEncoded
= *(BYTE
**)pbEncoded
;
140 *pbEncoded
++ = ASN_OCTETSTRING
;
141 CRYPT_EncodeLen(dataLen
, pbEncoded
,
148 static BOOL
CRYPT_EncodeDataContentInfoHeader(const CDataEncodeMsg
*msg
,
149 CRYPT_DATA_BLOB
*header
)
153 if (msg
->base
.streamed
&& msg
->base
.stream_info
.cbContent
== 0xffffffff)
155 static const BYTE headerValue
[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
156 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
158 header
->pbData
= LocalAlloc(0, sizeof(headerValue
));
161 header
->cbData
= sizeof(headerValue
);
162 memcpy(header
->pbData
, headerValue
, sizeof(headerValue
));
170 struct AsnConstructedItem constructed
= { 0,
171 &msg
->base
.stream_info
.cbContent
, CRYPT_EncodeContentLength
};
172 struct AsnEncodeSequenceItem items
[2] = {
173 { szOID_RSA_data
, CRYPT_AsnEncodeOid
, 0 },
174 { &constructed
, CRYPT_AsnEncodeConstructed
, 0 },
177 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
178 sizeof(items
) / sizeof(items
[0]), CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
179 (LPBYTE
)&header
->pbData
, &header
->cbData
);
182 /* Trick: subtract the content length from the reported length,
183 * as the actual content hasn't come yet.
185 header
->cbData
-= msg
->base
.stream_info
.cbContent
;
191 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
192 DWORD cbData
, BOOL fFinal
)
194 CDataEncodeMsg
*msg
= hCryptMsg
;
197 if (msg
->base
.state
== MsgStateFinalized
)
198 SetLastError(CRYPT_E_MSG_ERROR
);
199 else if (msg
->base
.streamed
)
203 if (msg
->base
.state
!= MsgStateUpdated
)
205 CRYPT_DATA_BLOB header
;
207 ret
= CRYPT_EncodeDataContentInfoHeader(msg
, &header
);
210 ret
= msg
->base
.stream_info
.pfnStreamOutput(
211 msg
->base
.stream_info
.pvArg
, header
.pbData
, header
.cbData
,
213 LocalFree(header
.pbData
);
216 /* Curiously, every indefinite-length streamed update appears to
217 * get its own tag and length, regardless of fFinal.
219 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
224 ret
= CRYPT_EncodeContentLength(X509_ASN_ENCODING
, NULL
,
225 &cbData
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (BYTE
*)&header
,
229 ret
= msg
->base
.stream_info
.pfnStreamOutput(
230 msg
->base
.stream_info
.pvArg
, header
, headerLen
,
237 ret
= msg
->base
.stream_info
.pfnStreamOutput(
238 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
240 msg
->base
.state
= MsgStateUpdated
;
244 msg
->base
.state
= MsgStateFinalized
;
245 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
247 BYTE indefinite_trailer
[6] = { 0 };
249 ret
= msg
->base
.stream_info
.pfnStreamOutput(
250 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
253 ret
= msg
->base
.stream_info
.pfnStreamOutput(
254 msg
->base
.stream_info
.pvArg
, indefinite_trailer
,
255 sizeof(indefinite_trailer
), TRUE
);
258 ret
= msg
->base
.stream_info
.pfnStreamOutput(
259 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
, TRUE
);
264 SetLastError(STATUS_ACCESS_VIOLATION
);
273 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
274 SetLastError(E_INVALIDARG
);
276 SetLastError(CRYPT_E_MSG_ERROR
);
280 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
282 msg
->base
.state
= MsgStateFinalized
;
283 /* non-streamed data messages don't allow non-final updates,
284 * don't bother checking whether data already exist, they can't.
286 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
287 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
288 &msg
->bare_content_len
);
294 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
301 else if (*pcbData
< len
)
304 SetLastError(ERROR_MORE_DATA
);
310 memcpy(pvData
, src
, len
);
315 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
316 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
318 CDataEncodeMsg
*msg
= hCryptMsg
;
323 case CMSG_CONTENT_PARAM
:
324 if (msg
->base
.streamed
)
325 SetLastError(E_INVALIDARG
);
328 CRYPT_CONTENT_INFO info
;
329 char rsa_data
[] = "1.2.840.113549.1.7.1";
331 info
.pszObjId
= rsa_data
;
332 info
.Content
.cbData
= msg
->bare_content_len
;
333 info
.Content
.pbData
= msg
->bare_content
;
334 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
338 case CMSG_BARE_CONTENT_PARAM
:
339 if (msg
->base
.streamed
)
340 SetLastError(E_INVALIDARG
);
342 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->bare_content
,
343 msg
->bare_content_len
);
346 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
351 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
352 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
358 SetLastError(E_INVALIDARG
);
361 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
364 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
365 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
,
366 CRYPT_DefaultMsgControl
);
367 msg
->bare_content_len
= sizeof(empty_data_content
);
368 msg
->bare_content
= (LPBYTE
)empty_data_content
;
373 typedef struct _CHashEncodeMsg
378 CRYPT_DATA_BLOB data
;
381 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
383 CHashEncodeMsg
*msg
= hCryptMsg
;
385 CryptMemFree(msg
->data
.pbData
);
386 CryptDestroyHash(msg
->hash
);
387 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
388 CryptReleaseContext(msg
->prov
, 0);
391 static BOOL
CRYPT_EncodePKCSDigestedData(CHashEncodeMsg
*msg
, void *pvData
,
396 DWORD size
= sizeof(algID
);
398 ret
= CryptGetHashParam(msg
->hash
, HP_ALGID
, (BYTE
*)&algID
, &size
, 0);
401 CRYPT_DIGESTED_DATA digestedData
= { 0 };
402 char oid_rsa_data
[] = szOID_RSA_data
;
404 digestedData
.version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
405 digestedData
.DigestAlgorithm
.pszObjId
= (LPSTR
)CertAlgIdToOID(algID
);
406 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
407 /* Quirk: OID is only encoded messages if an update has happened */
408 if (msg
->base
.state
!= MsgStateInit
)
409 digestedData
.ContentInfo
.pszObjId
= oid_rsa_data
;
410 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->data
.cbData
)
412 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &msg
->data
,
413 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
414 (LPBYTE
)&digestedData
.ContentInfo
.Content
.pbData
,
415 &digestedData
.ContentInfo
.Content
.cbData
);
417 if (msg
->base
.state
== MsgStateFinalized
)
419 size
= sizeof(DWORD
);
420 ret
= CryptGetHashParam(msg
->hash
, HP_HASHSIZE
,
421 (LPBYTE
)&digestedData
.hash
.cbData
, &size
, 0);
424 digestedData
.hash
.pbData
= CryptMemAlloc(
425 digestedData
.hash
.cbData
);
426 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
,
427 digestedData
.hash
.pbData
, &digestedData
.hash
.cbData
, 0);
431 ret
= CRYPT_AsnEncodePKCSDigestedData(&digestedData
, pvData
,
433 CryptMemFree(digestedData
.hash
.pbData
);
434 LocalFree(digestedData
.ContentInfo
.Content
.pbData
);
439 static BOOL
CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
440 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
442 CHashEncodeMsg
*msg
= hCryptMsg
;
445 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
450 case CMSG_BARE_CONTENT_PARAM
:
451 if (msg
->base
.streamed
)
452 SetLastError(E_INVALIDARG
);
454 ret
= CRYPT_EncodePKCSDigestedData(msg
, pvData
, pcbData
);
456 case CMSG_CONTENT_PARAM
:
458 CRYPT_CONTENT_INFO info
;
460 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
461 &info
.Content
.cbData
);
464 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
465 if (info
.Content
.pbData
)
467 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
468 info
.Content
.pbData
, &info
.Content
.cbData
);
471 char oid_rsa_hashed
[] = szOID_RSA_hashedData
;
473 info
.pszObjId
= oid_rsa_hashed
;
474 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
475 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
477 CryptMemFree(info
.Content
.pbData
);
484 case CMSG_COMPUTED_HASH_PARAM
:
485 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
487 case CMSG_VERSION_PARAM
:
488 if (msg
->base
.state
!= MsgStateFinalized
)
489 SetLastError(CRYPT_E_MSG_ERROR
);
492 DWORD version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
494 /* Since the data are always encoded as octets, the version is
495 * always 0 (see rfc3852, section 7)
497 ret
= CRYPT_CopyParam(pvData
, pcbData
, &version
, sizeof(version
));
501 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
506 static BOOL
CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
507 DWORD cbData
, BOOL fFinal
)
509 CHashEncodeMsg
*msg
= hCryptMsg
;
512 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
514 if (msg
->base
.state
== MsgStateFinalized
)
515 SetLastError(CRYPT_E_MSG_ERROR
);
516 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
518 /* Doesn't do much, as stream output is never called, and you
519 * can't get the content.
521 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
522 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
527 SetLastError(CRYPT_E_MSG_ERROR
);
530 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
533 msg
->data
.pbData
= CryptMemAlloc(cbData
);
534 if (msg
->data
.pbData
)
536 memcpy(msg
->data
.pbData
+ msg
->data
.cbData
, pbData
, cbData
);
537 msg
->data
.cbData
+= cbData
;
542 msg
->base
.state
= MsgStateFinalized
;
548 static HCRYPTMSG
CHashEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
549 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
552 const CMSG_HASHED_ENCODE_INFO
*info
= pvMsgEncodeInfo
;
556 if (info
->cbSize
!= sizeof(CMSG_HASHED_ENCODE_INFO
))
558 SetLastError(E_INVALIDARG
);
561 if (!(algID
= CertOIDToAlgId(info
->HashAlgorithm
.pszObjId
)))
563 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
566 if (info
->hCryptProv
)
567 prov
= info
->hCryptProv
;
570 prov
= CRYPT_GetDefaultProvider();
571 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
573 msg
= CryptMemAlloc(sizeof(CHashEncodeMsg
));
576 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
577 CHashEncodeMsg_Close
, CHashEncodeMsg_GetParam
, CHashEncodeMsg_Update
,
578 CRYPT_DefaultMsgControl
);
580 msg
->data
.cbData
= 0;
581 msg
->data
.pbData
= NULL
;
582 if (!CryptCreateHash(prov
, algID
, 0, 0, &msg
->hash
))
591 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
594 PCERT_INFO pCertInfo
;
595 HCRYPTPROV hCryptProv
;
597 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm
;
600 PCRYPT_ATTRIBUTE rgAuthAttr
;
602 PCRYPT_ATTRIBUTE rgUnauthAttr
;
604 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm
;
605 void *pvHashEncryptionAuxInfo
;
606 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS
;
608 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
612 PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners
;
614 PCERT_BLOB rgCertEncoded
;
616 PCRL_BLOB rgCrlEncoded
;
617 DWORD cAttrCertEncoded
;
618 PCERT_BLOB rgAttrCertEncoded
;
619 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS
, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS
;
621 static BOOL
CRYPT_IsValidSigner(const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*signer
)
623 if (signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO
) &&
624 signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
626 SetLastError(E_INVALIDARG
);
629 if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
631 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
633 SetLastError(E_INVALIDARG
);
636 if (!signer
->pCertInfo
->Issuer
.cbData
)
638 SetLastError(E_INVALIDARG
);
642 else if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
644 switch (signer
->SignerId
.dwIdChoice
)
647 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
649 SetLastError(E_INVALIDARG
);
652 if (!signer
->pCertInfo
->Issuer
.cbData
)
654 SetLastError(E_INVALIDARG
);
658 case CERT_ID_ISSUER_SERIAL_NUMBER
:
659 if (!signer
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
)
661 SetLastError(E_INVALIDARG
);
664 if (!signer
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
666 SetLastError(E_INVALIDARG
);
670 case CERT_ID_KEY_IDENTIFIER
:
671 if (!signer
->SignerId
.u
.KeyId
.cbData
)
673 SetLastError(E_INVALIDARG
);
678 SetLastError(E_INVALIDARG
);
680 if (signer
->HashEncryptionAlgorithm
.pszObjId
)
682 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
686 if (!signer
->hCryptProv
)
688 SetLastError(E_INVALIDARG
);
691 if (!CertOIDToAlgId(signer
->HashAlgorithm
.pszObjId
))
693 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
699 static BOOL
CRYPT_ConstructBlob(CRYPT_DATA_BLOB
*out
, const CRYPT_DATA_BLOB
*in
)
703 out
->cbData
= in
->cbData
;
706 out
->pbData
= CryptMemAlloc(out
->cbData
);
708 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
717 static BOOL
CRYPT_ConstructBlobArray(DWORD
*outCBlobs
,
718 PCRYPT_DATA_BLOB
*outPBlobs
, DWORD cBlobs
, const CRYPT_DATA_BLOB
*pBlobs
)
725 *outPBlobs
= CryptMemAlloc(cBlobs
* sizeof(CRYPT_DATA_BLOB
));
730 memset(*outPBlobs
, 0, cBlobs
* sizeof(CRYPT_DATA_BLOB
));
731 for (i
= 0; ret
&& i
< cBlobs
; i
++)
732 ret
= CRYPT_ConstructBlob(&(*outPBlobs
)[i
], &pBlobs
[i
]);
740 static void CRYPT_FreeBlobArray(DWORD cBlobs
, PCRYPT_DATA_BLOB blobs
)
744 for (i
= 0; i
< cBlobs
; i
++)
745 CryptMemFree(blobs
[i
].pbData
);
749 static BOOL
CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE
*out
,
750 const CRYPT_ATTRIBUTE
*in
)
754 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
757 strcpy(out
->pszObjId
, in
->pszObjId
);
758 ret
= CRYPT_ConstructBlobArray(&out
->cValue
, &out
->rgValue
,
759 in
->cValue
, in
->rgValue
);
766 static BOOL
CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES
*out
,
767 const CRYPT_ATTRIBUTES
*in
)
771 out
->cAttr
= in
->cAttr
;
774 out
->rgAttr
= CryptMemAlloc(out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
779 memset(out
->rgAttr
, 0, out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
780 for (i
= 0; ret
&& i
< out
->cAttr
; i
++)
781 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[i
], &in
->rgAttr
[i
]);
791 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
792 static BOOL
CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO
*info
,
793 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*in
)
797 if (in
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
799 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
800 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
801 &in
->pCertInfo
->Issuer
);
803 ret
= CRYPT_ConstructBlob(
804 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
805 &in
->pCertInfo
->SerialNumber
);
806 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
807 info
->HashEncryptionAlgorithm
.pszObjId
=
808 in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
;
810 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
811 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.Parameters
);
815 const CRYPT_ALGORITHM_IDENTIFIER
*pEncrAlg
;
817 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS).
818 * See CRYPT_IsValidSigner.
820 if (!in
->SignerId
.dwIdChoice
)
822 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
823 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
824 &in
->pCertInfo
->Issuer
);
826 ret
= CRYPT_ConstructBlob(
827 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
828 &in
->pCertInfo
->SerialNumber
);
829 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
831 else if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
833 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
834 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
835 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
836 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
);
838 ret
= CRYPT_ConstructBlob(
839 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
840 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
);
844 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */
845 info
->dwVersion
= CMSG_SIGNER_INFO_V3
;
846 info
->SignerId
.dwIdChoice
= CERT_ID_KEY_IDENTIFIER
;
847 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.KeyId
,
848 &in
->SignerId
.u
.KeyId
);
850 pEncrAlg
= in
->HashEncryptionAlgorithm
.pszObjId
?
851 &in
->HashEncryptionAlgorithm
:
852 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
;
853 info
->HashEncryptionAlgorithm
.pszObjId
= pEncrAlg
->pszObjId
;
855 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
856 &pEncrAlg
->Parameters
);
858 /* Assumption: algorithm IDs will point to static strings, not
859 * stack-based ones, so copying the pointer values is safe.
861 info
->HashAlgorithm
.pszObjId
= in
->HashAlgorithm
.pszObjId
;
863 ret
= CRYPT_ConstructBlob(&info
->HashAlgorithm
.Parameters
,
864 &in
->HashAlgorithm
.Parameters
);
866 ret
= CRYPT_ConstructAttributes(&info
->AuthAttrs
,
867 (CRYPT_ATTRIBUTES
*)&in
->cAuthAttr
);
869 ret
= CRYPT_ConstructAttributes(&info
->UnauthAttrs
,
870 (CRYPT_ATTRIBUTES
*)&in
->cUnauthAttr
);
874 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO
*info
)
878 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
880 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
881 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
884 CryptMemFree(info
->SignerId
.u
.KeyId
.pbData
);
885 CryptMemFree(info
->HashAlgorithm
.Parameters
.pbData
);
886 CryptMemFree(info
->HashEncryptionAlgorithm
.Parameters
.pbData
);
887 CryptMemFree(info
->EncryptedHash
.pbData
);
888 for (i
= 0; i
< info
->AuthAttrs
.cAttr
; i
++)
890 for (j
= 0; j
< info
->AuthAttrs
.rgAttr
[i
].cValue
; j
++)
891 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
892 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
);
893 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].pszObjId
);
895 CryptMemFree(info
->AuthAttrs
.rgAttr
);
896 for (i
= 0; i
< info
->UnauthAttrs
.cAttr
; i
++)
898 for (j
= 0; j
< info
->UnauthAttrs
.rgAttr
[i
].cValue
; j
++)
899 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
900 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
);
901 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].pszObjId
);
903 CryptMemFree(info
->UnauthAttrs
.rgAttr
);
906 typedef struct _CSignerHandles
908 HCRYPTHASH contentHash
;
909 HCRYPTHASH authAttrHash
;
912 typedef struct _CSignedMsgData
914 CRYPT_SIGNED_INFO
*info
;
916 CSignerHandles
*signerHandles
;
919 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
920 * Assumes signerIndex is a valid idnex, and that msg_data's info has already
923 static BOOL
CSignedMsgData_ConstructSignerHandles(CSignedMsgData
*msg_data
,
924 DWORD signerIndex
, HCRYPTPROV crypt_prov
)
929 algID
= CertOIDToAlgId(
930 msg_data
->info
->rgSignerInfo
[signerIndex
].HashAlgorithm
.pszObjId
);
931 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
932 &msg_data
->signerHandles
->contentHash
);
933 if (ret
&& msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
> 0)
934 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
935 &msg_data
->signerHandles
->authAttrHash
);
939 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
942 static BOOL
CSignedMsgData_AllocateHandles(CSignedMsgData
*msg_data
)
946 if (msg_data
->info
->cSignerInfo
)
948 msg_data
->signerHandles
=
949 CryptMemAlloc(msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
950 if (msg_data
->signerHandles
)
952 msg_data
->cSignerHandle
= msg_data
->info
->cSignerInfo
;
953 memset(msg_data
->signerHandles
, 0,
954 msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
958 msg_data
->cSignerHandle
= 0;
964 msg_data
->cSignerHandle
= 0;
965 msg_data
->signerHandles
= NULL
;
970 static void CSignedMsgData_CloseHandles(CSignedMsgData
*msg_data
)
974 for (i
= 0; i
< msg_data
->cSignerHandle
; i
++)
976 if (msg_data
->signerHandles
[i
].contentHash
)
977 CryptDestroyHash(msg_data
->signerHandles
[i
].contentHash
);
978 if (msg_data
->signerHandles
[i
].authAttrHash
)
979 CryptDestroyHash(msg_data
->signerHandles
[i
].authAttrHash
);
981 CryptMemFree(msg_data
->signerHandles
);
982 msg_data
->signerHandles
= NULL
;
983 msg_data
->cSignerHandle
= 0;
986 static BOOL
CSignedMsgData_UpdateHash(CSignedMsgData
*msg_data
,
987 const BYTE
*pbData
, DWORD cbData
)
992 for (i
= 0; ret
&& i
< msg_data
->cSignerHandle
; i
++)
993 ret
= CryptHashData(msg_data
->signerHandles
[i
].contentHash
, pbData
,
998 static BOOL
CRYPT_AppendAttribute(CRYPT_ATTRIBUTES
*out
,
999 const CRYPT_ATTRIBUTE
*in
)
1003 out
->rgAttr
= CryptMemRealloc(out
->rgAttr
,
1004 (out
->cAttr
+ 1) * sizeof(CRYPT_ATTRIBUTE
));
1007 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[out
->cAttr
], in
);
1014 static BOOL
CSignedMsgData_AppendMessageDigestAttribute(
1015 CSignedMsgData
*msg_data
, DWORD signerIndex
)
1019 CRYPT_HASH_BLOB hash
= { 0, NULL
}, encodedHash
= { 0, NULL
};
1020 char messageDigest
[] = szOID_RSA_messageDigest
;
1021 CRYPT_ATTRIBUTE messageDigestAttr
= { messageDigest
, 1, &encodedHash
};
1023 size
= sizeof(DWORD
);
1024 ret
= CryptGetHashParam(
1025 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHSIZE
,
1026 (LPBYTE
)&hash
.cbData
, &size
, 0);
1029 hash
.pbData
= CryptMemAlloc(hash
.cbData
);
1030 ret
= CryptGetHashParam(
1031 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHVAL
,
1032 hash
.pbData
, &hash
.cbData
, 0);
1035 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &hash
, CRYPT_ENCODE_ALLOC_FLAG
,
1036 NULL
, (LPBYTE
)&encodedHash
.pbData
, &encodedHash
.cbData
);
1039 ret
= CRYPT_AppendAttribute(
1040 &msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
,
1041 &messageDigestAttr
);
1042 LocalFree(encodedHash
.pbData
);
1045 CryptMemFree(hash
.pbData
);
1055 static BOOL
CSignedMsgData_UpdateAuthenticatedAttributes(
1056 CSignedMsgData
*msg_data
, SignOrVerify flag
)
1061 TRACE("(%p)\n", msg_data
);
1063 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1065 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1069 BYTE oid_rsa_data_encoded
[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
1070 0xf7,0x0d,0x01,0x07,0x01 };
1071 CRYPT_DATA_BLOB content
= { sizeof(oid_rsa_data_encoded
),
1072 oid_rsa_data_encoded
};
1073 char contentType
[] = szOID_RSA_contentType
;
1074 CRYPT_ATTRIBUTE contentTypeAttr
= { contentType
, 1, &content
};
1076 /* FIXME: does this depend on inner OID? */
1077 ret
= CRYPT_AppendAttribute(
1078 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
, &contentTypeAttr
);
1080 ret
= CSignedMsgData_AppendMessageDigestAttribute(msg_data
,
1085 LPBYTE encodedAttrs
;
1088 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, PKCS_ATTRIBUTES
,
1089 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
,
1090 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &encodedAttrs
, &size
);
1093 ret
= CryptHashData(
1094 msg_data
->signerHandles
[i
].authAttrHash
, encodedAttrs
,
1096 LocalFree(encodedAttrs
);
1101 TRACE("returning %d\n", ret
);
1105 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB
*hash
)
1110 for (i
= 0; i
< hash
->cbData
/ 2; i
++)
1112 tmp
= hash
->pbData
[hash
->cbData
- i
- 1];
1113 hash
->pbData
[hash
->cbData
- i
- 1] = hash
->pbData
[i
];
1114 hash
->pbData
[i
] = tmp
;
1118 static BOOL
CSignedMsgData_Sign(CSignedMsgData
*msg_data
)
1123 TRACE("(%p)\n", msg_data
);
1125 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1129 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1130 hash
= msg_data
->signerHandles
[i
].authAttrHash
;
1132 hash
= msg_data
->signerHandles
[i
].contentHash
;
1133 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0, NULL
,
1134 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1137 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
=
1139 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1140 if (msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
)
1142 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0,
1143 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
,
1144 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1147 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
);
1156 static BOOL
CSignedMsgData_Update(CSignedMsgData
*msg_data
,
1157 const BYTE
*pbData
, DWORD cbData
, BOOL fFinal
, SignOrVerify flag
)
1159 BOOL ret
= CSignedMsgData_UpdateHash(msg_data
, pbData
, cbData
);
1163 ret
= CSignedMsgData_UpdateAuthenticatedAttributes(msg_data
, flag
);
1164 if (ret
&& flag
== Sign
)
1165 ret
= CSignedMsgData_Sign(msg_data
);
1170 typedef struct _CSignedEncodeMsg
1174 CRYPT_DATA_BLOB data
;
1175 CSignedMsgData msg_data
;
1178 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1180 CSignedEncodeMsg
*msg
= hCryptMsg
;
1183 CryptMemFree(msg
->innerOID
);
1184 CryptMemFree(msg
->data
.pbData
);
1185 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCertEncoded
,
1186 msg
->msg_data
.info
->rgCertEncoded
);
1187 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCrlEncoded
,
1188 msg
->msg_data
.info
->rgCrlEncoded
);
1189 for (i
= 0; i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1190 CSignerInfo_Free(&msg
->msg_data
.info
->rgSignerInfo
[i
]);
1191 CSignedMsgData_CloseHandles(&msg
->msg_data
);
1192 CryptMemFree(msg
->msg_data
.info
->rgSignerInfo
);
1193 CryptMemFree(msg
->msg_data
.info
);
1196 static BOOL
CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1197 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1199 CSignedEncodeMsg
*msg
= hCryptMsg
;
1202 switch (dwParamType
)
1204 case CMSG_CONTENT_PARAM
:
1206 CRYPT_CONTENT_INFO info
;
1208 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1209 &info
.Content
.cbData
);
1212 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1213 if (info
.Content
.pbData
)
1215 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1216 info
.Content
.pbData
, &info
.Content
.cbData
);
1219 char oid_rsa_signed
[] = szOID_RSA_signedData
;
1221 info
.pszObjId
= oid_rsa_signed
;
1222 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1223 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1225 CryptMemFree(info
.Content
.pbData
);
1232 case CMSG_BARE_CONTENT_PARAM
:
1234 CRYPT_SIGNED_INFO info
;
1235 BOOL freeContent
= FALSE
;
1237 info
= *msg
->msg_data
.info
;
1238 if (!msg
->innerOID
|| !strcmp(msg
->innerOID
, szOID_RSA_data
))
1240 char oid_rsa_data
[] = szOID_RSA_data
;
1242 /* Quirk: OID is only encoded messages if an update has happened */
1243 if (msg
->base
.state
!= MsgStateInit
)
1244 info
.content
.pszObjId
= oid_rsa_data
;
1246 info
.content
.pszObjId
= NULL
;
1247 if (msg
->data
.cbData
)
1249 CRYPT_DATA_BLOB blob
= { msg
->data
.cbData
, msg
->data
.pbData
};
1251 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1252 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
1253 &info
.content
.Content
.pbData
, &info
.content
.Content
.cbData
);
1258 info
.content
.Content
.cbData
= 0;
1259 info
.content
.Content
.pbData
= NULL
;
1265 info
.content
.pszObjId
= msg
->innerOID
;
1266 info
.content
.Content
.cbData
= msg
->data
.cbData
;
1267 info
.content
.Content
.pbData
= msg
->data
.pbData
;
1272 ret
= CRYPT_AsnEncodeCMSSignedInfo(&info
, pvData
, pcbData
);
1274 LocalFree(info
.content
.Content
.pbData
);
1278 case CMSG_COMPUTED_HASH_PARAM
:
1279 if (dwIndex
>= msg
->msg_data
.cSignerHandle
)
1280 SetLastError(CRYPT_E_INVALID_INDEX
);
1282 ret
= CryptGetHashParam(
1283 msg
->msg_data
.signerHandles
[dwIndex
].contentHash
, HP_HASHVAL
,
1284 pvData
, pcbData
, 0);
1286 case CMSG_ENCODED_SIGNER
:
1287 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1288 SetLastError(CRYPT_E_INVALID_INDEX
);
1290 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1291 CMS_SIGNER_INFO
, &msg
->msg_data
.info
->rgSignerInfo
[dwIndex
], 0,
1292 NULL
, pvData
, pcbData
);
1294 case CMSG_VERSION_PARAM
:
1295 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->msg_data
.info
->version
,
1296 sizeof(msg
->msg_data
.info
->version
));
1299 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1304 static BOOL
CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1305 DWORD cbData
, BOOL fFinal
)
1307 CSignedEncodeMsg
*msg
= hCryptMsg
;
1310 if (msg
->base
.state
== MsgStateFinalized
)
1311 SetLastError(CRYPT_E_MSG_ERROR
);
1312 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1314 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
, fFinal
,
1316 if (msg
->base
.streamed
)
1317 FIXME("streamed partial stub\n");
1318 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1323 SetLastError(CRYPT_E_MSG_ERROR
);
1328 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1329 if (msg
->data
.pbData
)
1331 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1332 msg
->data
.cbData
= cbData
;
1339 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
,
1341 msg
->base
.state
= MsgStateFinalized
;
1347 static HCRYPTMSG
CSignedEncodeMsg_Open(DWORD dwFlags
,
1348 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1349 PCMSG_STREAM_INFO pStreamInfo
)
1351 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1353 CSignedEncodeMsg
*msg
;
1355 if (info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO
) &&
1356 info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1358 SetLastError(E_INVALIDARG
);
1361 if (info
->cbSize
== sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
) &&
1362 info
->cAttrCertEncoded
)
1364 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1367 for (i
= 0; i
< info
->cSigners
; i
++)
1368 if (!CRYPT_IsValidSigner(&info
->rgSigners
[i
]))
1370 msg
= CryptMemAlloc(sizeof(CSignedEncodeMsg
));
1375 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1376 CSignedEncodeMsg_Close
, CSignedEncodeMsg_GetParam
,
1377 CSignedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1378 if (pszInnerContentObjID
)
1380 msg
->innerOID
= CryptMemAlloc(strlen(pszInnerContentObjID
) + 1);
1382 strcpy(msg
->innerOID
, pszInnerContentObjID
);
1387 msg
->innerOID
= NULL
;
1388 msg
->data
.cbData
= 0;
1389 msg
->data
.pbData
= NULL
;
1391 msg
->msg_data
.info
= CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO
));
1393 msg
->msg_data
.info
= NULL
;
1394 if (msg
->msg_data
.info
)
1396 memset(msg
->msg_data
.info
, 0, sizeof(CRYPT_SIGNED_INFO
));
1397 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V1
;
1405 msg
->msg_data
.info
->rgSignerInfo
=
1406 CryptMemAlloc(info
->cSigners
* sizeof(CMSG_CMS_SIGNER_INFO
));
1407 if (msg
->msg_data
.info
->rgSignerInfo
)
1409 msg
->msg_data
.info
->cSignerInfo
= info
->cSigners
;
1410 memset(msg
->msg_data
.info
->rgSignerInfo
, 0,
1411 msg
->msg_data
.info
->cSignerInfo
*
1412 sizeof(CMSG_CMS_SIGNER_INFO
));
1413 ret
= CSignedMsgData_AllocateHandles(&msg
->msg_data
);
1414 for (i
= 0; ret
&& i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1416 if (info
->rgSigners
[i
].SignerId
.dwIdChoice
==
1417 CERT_ID_KEY_IDENTIFIER
)
1418 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V3
;
1419 ret
= CSignerInfo_Construct(
1420 &msg
->msg_data
.info
->rgSignerInfo
[i
],
1421 &info
->rgSigners
[i
]);
1424 ret
= CSignedMsgData_ConstructSignerHandles(
1425 &msg
->msg_data
, i
, info
->rgSigners
[i
].hCryptProv
);
1426 if (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1427 CryptReleaseContext(info
->rgSigners
[i
].hCryptProv
,
1437 msg
->msg_data
.info
->cSignerInfo
= 0;
1438 msg
->msg_data
.signerHandles
= NULL
;
1439 msg
->msg_data
.cSignerHandle
= 0;
1443 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCertEncoded
,
1444 &msg
->msg_data
.info
->rgCertEncoded
, info
->cCertEncoded
,
1445 info
->rgCertEncoded
);
1447 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCrlEncoded
,
1448 &msg
->msg_data
.info
->rgCrlEncoded
, info
->cCrlEncoded
,
1449 info
->rgCrlEncoded
);
1452 CSignedEncodeMsg_Close(msg
);
1459 typedef struct _CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
1462 HCRYPTPROV_LEGACY hCryptProv
;
1463 CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm
;
1464 void *pvEncryptionAuxInfo
;
1466 PCERT_INFO
*rgpRecipientCert
;
1467 PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients
;
1469 PCERT_BLOB rgCertEncoded
;
1471 PCRL_BLOB rgCrlEncoded
;
1472 DWORD cAttrCertEncoded
;
1473 PCERT_BLOB rgAttrCertEncoded
;
1474 DWORD cUnprotectedAttr
;
1475 PCRYPT_ATTRIBUTE rgUnprotectedAttr
;
1476 } CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
, *PCMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
;
1478 typedef struct _CEnvelopedEncodeMsg
1481 CRYPT_ALGORITHM_IDENTIFIER algo
;
1484 DWORD cRecipientInfo
;
1485 CMSG_KEY_TRANS_RECIPIENT_INFO
*recipientInfo
;
1486 CRYPT_DATA_BLOB data
;
1487 } CEnvelopedEncodeMsg
;
1489 static BOOL
CRYPT_ConstructAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
1490 const CRYPT_ALGORITHM_IDENTIFIER
*in
)
1492 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
1495 strcpy(out
->pszObjId
, in
->pszObjId
);
1496 return CRYPT_ConstructBlob(&out
->Parameters
, &in
->Parameters
);
1502 static BOOL
CRYPT_ConstructBitBlob(CRYPT_BIT_BLOB
*out
, const CRYPT_BIT_BLOB
*in
)
1504 out
->cbData
= in
->cbData
;
1505 out
->cUnusedBits
= in
->cUnusedBits
;
1508 out
->pbData
= CryptMemAlloc(out
->cbData
);
1510 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
1519 static BOOL
CRYPT_GenKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, ALG_ID algID
)
1521 static HCRYPTOIDFUNCSET set
= NULL
;
1522 PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY genKeyFunc
= NULL
;
1523 HCRYPTOIDFUNCADDR hFunc
;
1527 set
= CryptInitOIDFunctionSet(CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC
, 0);
1528 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1529 info
->ContentEncryptionAlgorithm
.pszObjId
, 0, (void **)&genKeyFunc
, &hFunc
);
1532 ret
= genKeyFunc(info
, 0, NULL
);
1533 CryptFreeOIDFunctionAddress(hFunc
, 0);
1536 ret
= CryptGenKey(info
->hCryptProv
, algID
, CRYPT_EXPORTABLE
,
1537 &info
->hContentEncryptKey
);
1541 static BOOL WINAPI
CRYPT_ExportKeyTrans(
1542 PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo
,
1543 PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo
,
1544 PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo
,
1545 DWORD dwFlags
, void *pvReserved
)
1547 CERT_PUBLIC_KEY_INFO keyInfo
;
1551 ret
= CRYPT_ConstructAlgorithmId(&keyInfo
.Algorithm
,
1552 &pKeyTransEncodeInfo
->KeyEncryptionAlgorithm
);
1554 CRYPT_ConstructBitBlob(&keyInfo
.PublicKey
,
1555 &pKeyTransEncodeInfo
->RecipientPublicKey
);
1558 ret
= CryptImportPublicKeyInfo(pKeyTransEncodeInfo
->hCryptProv
,
1559 X509_ASN_ENCODING
, &keyInfo
, &expKey
);
1564 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
, expKey
,
1565 SIMPLEBLOB
, 0, NULL
, &size
);
1570 keyBlob
= CryptMemAlloc(size
);
1573 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
,
1574 expKey
, SIMPLEBLOB
, 0, keyBlob
, &size
);
1577 DWORD head
= sizeof(BLOBHEADER
) + sizeof(ALG_ID
);
1579 pKeyTransEncryptInfo
->EncryptedKey
.pbData
=
1580 CryptMemAlloc(size
- head
);
1581 if (pKeyTransEncryptInfo
->EncryptedKey
.pbData
)
1585 pKeyTransEncryptInfo
->EncryptedKey
.cbData
= size
- head
;
1586 for (i
= size
- 1; i
>= head
; --i
, ++k
)
1587 pKeyTransEncryptInfo
->EncryptedKey
.pbData
[k
] =
1593 CryptMemFree(keyBlob
);
1598 CryptDestroyKey(expKey
);
1601 CryptMemFree(keyInfo
.PublicKey
.pbData
);
1602 CryptMemFree(keyInfo
.Algorithm
.pszObjId
);
1603 CryptMemFree(keyInfo
.Algorithm
.Parameters
.pbData
);
1607 static BOOL
CRYPT_ExportEncryptedKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, DWORD i
,
1608 CRYPT_DATA_BLOB
*key
)
1610 static HCRYPTOIDFUNCSET set
= NULL
;
1611 PFN_CMSG_EXPORT_KEY_TRANS exportKeyFunc
= NULL
;
1612 HCRYPTOIDFUNCADDR hFunc
= NULL
;
1613 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1614 info
->rgCmsRecipients
[i
].u
.pKeyTrans
;
1615 CMSG_KEY_TRANS_ENCRYPT_INFO encryptInfo
;
1618 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
1619 encryptInfo
.cbSize
= sizeof(encryptInfo
);
1620 encryptInfo
.dwRecipientIndex
= i
;
1621 ret
= CRYPT_ConstructAlgorithmId(&encryptInfo
.KeyEncryptionAlgorithm
,
1622 &encodeInfo
->KeyEncryptionAlgorithm
);
1625 set
= CryptInitOIDFunctionSet(CMSG_OID_EXPORT_KEY_TRANS_FUNC
, 0);
1626 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1627 encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
, 0, (void **)&exportKeyFunc
,
1630 exportKeyFunc
= CRYPT_ExportKeyTrans
;
1633 ret
= exportKeyFunc(info
, encodeInfo
, &encryptInfo
, 0, NULL
);
1636 key
->cbData
= encryptInfo
.EncryptedKey
.cbData
;
1637 key
->pbData
= encryptInfo
.EncryptedKey
.pbData
;
1641 CryptFreeOIDFunctionAddress(hFunc
, 0);
1643 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
);
1644 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.Parameters
.pbData
);
1648 static LPVOID WINAPI
mem_alloc(size_t size
)
1650 return HeapAlloc(GetProcessHeap(), 0, size
);
1653 static VOID WINAPI
mem_free(LPVOID pv
)
1655 HeapFree(GetProcessHeap(), 0, pv
);
1659 static BOOL
CContentEncryptInfo_Construct(CMSG_CONTENT_ENCRYPT_INFO
*info
,
1660 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*in
, HCRYPTPROV prov
)
1664 info
->cbSize
= sizeof(CMSG_CONTENT_ENCRYPT_INFO
);
1665 info
->hCryptProv
= prov
;
1666 ret
= CRYPT_ConstructAlgorithmId(&info
->ContentEncryptionAlgorithm
,
1667 &in
->ContentEncryptionAlgorithm
);
1668 info
->pvEncryptionAuxInfo
= in
->pvEncryptionAuxInfo
;
1669 info
->cRecipients
= in
->cRecipients
;
1672 info
->rgCmsRecipients
= CryptMemAlloc(in
->cRecipients
*
1673 sizeof(CMSG_RECIPIENT_ENCODE_INFO
));
1674 if (info
->rgCmsRecipients
)
1678 for (i
= 0; ret
&& i
< in
->cRecipients
; ++i
)
1680 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
;
1681 CERT_INFO
*cert
= in
->rgpRecipientCert
[i
];
1683 info
->rgCmsRecipients
[i
].dwRecipientChoice
=
1684 CMSG_KEY_TRANS_RECIPIENT
;
1685 encodeInfo
= CryptMemAlloc(sizeof(*encodeInfo
));
1686 info
->rgCmsRecipients
[i
].u
.pKeyTrans
= encodeInfo
;
1689 encodeInfo
->cbSize
= sizeof(*encodeInfo
);
1690 ret
= CRYPT_ConstructAlgorithmId(
1691 &encodeInfo
->KeyEncryptionAlgorithm
,
1692 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1693 encodeInfo
->pvKeyEncryptionAuxInfo
= NULL
;
1694 encodeInfo
->hCryptProv
= prov
;
1696 ret
= CRYPT_ConstructBitBlob(
1697 &encodeInfo
->RecipientPublicKey
,
1698 &cert
->SubjectPublicKeyInfo
.PublicKey
);
1700 ret
= CRYPT_ConstructBlob(
1701 &encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.Issuer
,
1704 ret
= CRYPT_ConstructBlob(
1705 &encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
,
1706 &cert
->SerialNumber
);
1715 info
->pfnAlloc
= mem_alloc
;
1716 info
->pfnFree
= mem_free
;
1720 static void CContentEncryptInfo_Free(CMSG_CONTENT_ENCRYPT_INFO
*info
)
1722 CryptMemFree(info
->ContentEncryptionAlgorithm
.pszObjId
);
1723 CryptMemFree(info
->ContentEncryptionAlgorithm
.Parameters
.pbData
);
1724 if (info
->rgCmsRecipients
)
1728 for (i
= 0; i
< info
->cRecipients
; ++i
)
1730 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1731 info
->rgCmsRecipients
[i
].u
.pKeyTrans
;
1733 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.pszObjId
);
1734 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1735 CryptMemFree(encodeInfo
->RecipientPublicKey
.pbData
);
1737 encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
1739 encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
1740 CryptMemFree(encodeInfo
);
1742 CryptMemFree(info
->rgCmsRecipients
);
1746 static BOOL
CRecipientInfo_Construct(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
,
1747 const CERT_INFO
*cert
, CRYPT_DATA_BLOB
*key
)
1751 info
->dwVersion
= CMSG_KEY_TRANS_PKCS_1_5_VERSION
;
1752 info
->RecipientId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
1753 ret
= CRYPT_ConstructBlob(&info
->RecipientId
.u
.IssuerSerialNumber
.Issuer
,
1756 ret
= CRYPT_ConstructBlob(
1757 &info
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
,
1758 &cert
->SerialNumber
);
1760 ret
= CRYPT_ConstructAlgorithmId(&info
->KeyEncryptionAlgorithm
,
1761 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1762 info
->EncryptedKey
.cbData
= key
->cbData
;
1763 info
->EncryptedKey
.pbData
= key
->pbData
;
1767 static void CRecipientInfo_Free(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
)
1769 CryptMemFree(info
->RecipientId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
1770 CryptMemFree(info
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
1771 CryptMemFree(info
->KeyEncryptionAlgorithm
.pszObjId
);
1772 CryptMemFree(info
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1773 CryptMemFree(info
->EncryptedKey
.pbData
);
1776 static void CEnvelopedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1778 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1780 CryptMemFree(msg
->algo
.pszObjId
);
1781 CryptMemFree(msg
->algo
.Parameters
.pbData
);
1782 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1783 CryptReleaseContext(msg
->prov
, 0);
1784 CryptDestroyKey(msg
->key
);
1785 if (msg
->recipientInfo
)
1789 for (i
= 0; i
< msg
->cRecipientInfo
; ++i
)
1790 CRecipientInfo_Free(&msg
->recipientInfo
[i
]);
1791 CryptMemFree(msg
->recipientInfo
);
1793 CryptMemFree(msg
->data
.pbData
);
1796 static BOOL
CEnvelopedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1797 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1799 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1802 switch (dwParamType
)
1804 case CMSG_BARE_CONTENT_PARAM
:
1805 if (msg
->base
.streamed
)
1806 SetLastError(E_INVALIDARG
);
1809 char oid_rsa_data
[] = szOID_RSA_data
;
1810 CRYPT_ENVELOPED_DATA envelopedData
= {
1811 CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION
, msg
->cRecipientInfo
,
1812 msg
->recipientInfo
, { oid_rsa_data
, {
1814 { msg
->algo
.Parameters
.cbData
, msg
->algo
.Parameters
.pbData
}
1816 { msg
->data
.cbData
, msg
->data
.pbData
}
1820 ret
= CRYPT_AsnEncodePKCSEnvelopedData(&envelopedData
, pvData
,
1824 case CMSG_CONTENT_PARAM
:
1826 CRYPT_CONTENT_INFO info
;
1828 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1829 &info
.Content
.cbData
);
1832 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1833 if (info
.Content
.pbData
)
1835 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1836 info
.Content
.pbData
, &info
.Content
.cbData
);
1839 char oid_rsa_enveloped
[] = szOID_RSA_envelopedData
;
1841 info
.pszObjId
= oid_rsa_enveloped
;
1842 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1843 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1845 CryptMemFree(info
.Content
.pbData
);
1853 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1858 static BOOL
CEnvelopedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1859 DWORD cbData
, BOOL fFinal
)
1861 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1864 if (msg
->base
.state
== MsgStateFinalized
)
1865 SetLastError(CRYPT_E_MSG_ERROR
);
1866 else if (msg
->base
.streamed
)
1868 FIXME("streamed stub\n");
1869 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1876 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1877 SetLastError(E_INVALIDARG
);
1879 SetLastError(CRYPT_E_MSG_ERROR
);
1885 DWORD dataLen
= cbData
;
1887 msg
->data
.cbData
= cbData
;
1888 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1889 if (msg
->data
.pbData
)
1891 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1892 ret
= CryptEncrypt(msg
->key
, 0, TRUE
, 0, msg
->data
.pbData
,
1893 &dataLen
, msg
->data
.cbData
);
1894 msg
->data
.cbData
= dataLen
;
1895 if (dataLen
> cbData
)
1897 msg
->data
.pbData
= CryptMemRealloc(msg
->data
.pbData
,
1899 if (msg
->data
.pbData
)
1902 ret
= CryptEncrypt(msg
->key
, 0, TRUE
, 0,
1903 msg
->data
.pbData
, &dataLen
, msg
->data
.cbData
);
1909 CryptMemFree(msg
->data
.pbData
);
1915 msg
->data
.cbData
= 0;
1916 msg
->data
.pbData
= NULL
;
1921 msg
->base
.state
= MsgStateFinalized
;
1927 static HCRYPTMSG
CEnvelopedEncodeMsg_Open(DWORD dwFlags
,
1928 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1929 PCMSG_STREAM_INFO pStreamInfo
)
1931 CEnvelopedEncodeMsg
*msg
;
1932 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1936 if (info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO
) &&
1937 info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1939 SetLastError(E_INVALIDARG
);
1942 if (info
->cbSize
== sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1943 FIXME("CMS fields unsupported\n");
1944 if (!(algID
= CertOIDToAlgId(info
->ContentEncryptionAlgorithm
.pszObjId
)))
1946 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
1949 if (info
->cRecipients
&& !info
->rgpRecipientCert
)
1951 SetLastError(E_INVALIDARG
);
1954 if (info
->hCryptProv
)
1955 prov
= info
->hCryptProv
;
1958 prov
= CRYPT_GetDefaultProvider();
1959 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
1961 msg
= CryptMemAlloc(sizeof(CEnvelopedEncodeMsg
));
1964 CRYPT_DATA_BLOB encryptedKey
= { 0, NULL
};
1965 CMSG_CONTENT_ENCRYPT_INFO encryptInfo
;
1969 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1970 CEnvelopedEncodeMsg_Close
, CEnvelopedEncodeMsg_GetParam
,
1971 CEnvelopedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1972 ret
= CRYPT_ConstructAlgorithmId(&msg
->algo
,
1973 &info
->ContentEncryptionAlgorithm
);
1975 msg
->data
.cbData
= 0;
1976 msg
->data
.pbData
= NULL
;
1977 msg
->cRecipientInfo
= info
->cRecipients
;
1978 msg
->recipientInfo
= CryptMemAlloc(info
->cRecipients
*
1979 sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
));
1980 if (!msg
->recipientInfo
)
1982 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
1985 ret
= CContentEncryptInfo_Construct(&encryptInfo
, info
, prov
);
1988 ret
= CRYPT_GenKey(&encryptInfo
, algID
);
1990 msg
->key
= encryptInfo
.hContentEncryptKey
;
1993 for (i
= 0; ret
&& i
< msg
->cRecipientInfo
; ++i
)
1995 ret
= CRYPT_ExportEncryptedKey(&encryptInfo
, i
, &encryptedKey
);
1997 ret
= CRecipientInfo_Construct(&msg
->recipientInfo
[i
],
1998 info
->rgpRecipientCert
[i
], &encryptedKey
);
2000 CContentEncryptInfo_Free(&encryptInfo
);
2007 if (!msg
&& (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
))
2008 CryptReleaseContext(prov
, 0);
2012 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
2013 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
2014 PCMSG_STREAM_INFO pStreamInfo
)
2016 HCRYPTMSG msg
= NULL
;
2018 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
2019 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
2021 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
2023 SetLastError(E_INVALIDARG
);
2029 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2030 pszInnerContentObjID
, pStreamInfo
);
2033 msg
= CHashEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2034 pszInnerContentObjID
, pStreamInfo
);
2037 msg
= CSignedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2038 pszInnerContentObjID
, pStreamInfo
);
2040 case CMSG_ENVELOPED
:
2041 msg
= CEnvelopedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2042 pszInnerContentObjID
, pStreamInfo
);
2044 case CMSG_SIGNED_AND_ENVELOPED
:
2045 case CMSG_ENCRYPTED
:
2046 /* defined but invalid, fall through */
2048 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2053 typedef struct _CEnvelopedDecodeMsg
2055 CRYPT_ENVELOPED_DATA
*data
;
2056 HCRYPTPROV crypt_prov
;
2057 CRYPT_DATA_BLOB content
;
2059 } CEnvelopedDecodeMsg
;
2061 typedef struct _CDecodeMsg
2065 HCRYPTPROV crypt_prov
;
2068 CSignedMsgData signed_data
;
2069 CEnvelopedDecodeMsg enveloped_data
;
2071 CRYPT_DATA_BLOB msg_data
;
2072 CRYPT_DATA_BLOB detached_data
;
2073 PCONTEXT_PROPERTY_LIST properties
;
2076 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg
)
2078 CDecodeMsg
*msg
= hCryptMsg
;
2080 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
2081 CryptReleaseContext(msg
->crypt_prov
, 0);
2086 CryptDestroyHash(msg
->u
.hash
);
2088 case CMSG_ENVELOPED
:
2089 if (msg
->u
.enveloped_data
.crypt_prov
)
2090 CryptReleaseContext(msg
->u
.enveloped_data
.crypt_prov
, 0);
2091 LocalFree(msg
->u
.enveloped_data
.data
);
2092 CryptMemFree(msg
->u
.enveloped_data
.content
.pbData
);
2095 if (msg
->u
.signed_data
.info
)
2097 LocalFree(msg
->u
.signed_data
.info
);
2098 CSignedMsgData_CloseHandles(&msg
->u
.signed_data
);
2102 CryptMemFree(msg
->msg_data
.pbData
);
2103 CryptMemFree(msg
->detached_data
.pbData
);
2104 ContextPropertyList_Free(msg
->properties
);
2107 static BOOL
CDecodeMsg_CopyData(CRYPT_DATA_BLOB
*blob
, const BYTE
*pbData
,
2115 blob
->pbData
= CryptMemRealloc(blob
->pbData
,
2116 blob
->cbData
+ cbData
);
2118 blob
->pbData
= CryptMemAlloc(cbData
);
2121 memcpy(blob
->pbData
+ blob
->cbData
, pbData
, cbData
);
2122 blob
->cbData
+= cbData
;
2130 static BOOL
CDecodeMsg_DecodeDataContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
)
2133 CRYPT_DATA_BLOB
*data
;
2136 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
2137 blob
->pbData
, blob
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &data
, &size
);
2140 ret
= ContextPropertyList_SetProperty(msg
->properties
,
2141 CMSG_CONTENT_PARAM
, data
->pbData
, data
->cbData
);
2147 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg
*msg
, DWORD param
,
2148 const CRYPT_ALGORITHM_IDENTIFIER
*id
)
2150 static const BYTE nullParams
[] = { ASN_NULL
, 0 };
2151 CRYPT_ALGORITHM_IDENTIFIER
*copy
;
2152 DWORD len
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
2154 /* Linearize algorithm id */
2155 len
+= strlen(id
->pszObjId
) + 1;
2156 len
+= id
->Parameters
.cbData
;
2157 copy
= CryptMemAlloc(len
);
2161 (LPSTR
)((BYTE
*)copy
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2162 strcpy(copy
->pszObjId
, id
->pszObjId
);
2163 copy
->Parameters
.pbData
= (BYTE
*)copy
->pszObjId
+ strlen(id
->pszObjId
)
2165 /* Trick: omit NULL parameters */
2166 if (id
->Parameters
.cbData
== sizeof(nullParams
) &&
2167 !memcmp(id
->Parameters
.pbData
, nullParams
, sizeof(nullParams
)))
2169 copy
->Parameters
.cbData
= 0;
2170 len
-= sizeof(nullParams
);
2173 copy
->Parameters
.cbData
= id
->Parameters
.cbData
;
2174 if (copy
->Parameters
.cbData
)
2175 memcpy(copy
->Parameters
.pbData
, id
->Parameters
.pbData
,
2176 id
->Parameters
.cbData
);
2177 ContextPropertyList_SetProperty(msg
->properties
, param
, (BYTE
*)copy
,
2183 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER
*id
)
2185 id
->pszObjId
= (LPSTR
)((BYTE
*)id
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2186 id
->Parameters
.pbData
= (BYTE
*)id
->pszObjId
+ strlen(id
->pszObjId
) + 1;
2189 static BOOL
CDecodeMsg_DecodeHashedContent(CDecodeMsg
*msg
,
2190 const CRYPT_DER_BLOB
*blob
)
2193 CRYPT_DIGESTED_DATA
*digestedData
;
2196 ret
= CRYPT_AsnDecodePKCSDigestedData(blob
->pbData
, blob
->cbData
,
2197 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_DIGESTED_DATA
*)&digestedData
,
2201 ContextPropertyList_SetProperty(msg
->properties
, CMSG_VERSION_PARAM
,
2202 (const BYTE
*)&digestedData
->version
, sizeof(digestedData
->version
));
2203 CDecodeMsg_SaveAlgorithmID(msg
, CMSG_HASH_ALGORITHM_PARAM
,
2204 &digestedData
->DigestAlgorithm
);
2205 ContextPropertyList_SetProperty(msg
->properties
,
2206 CMSG_INNER_CONTENT_TYPE_PARAM
,
2207 (const BYTE
*)digestedData
->ContentInfo
.pszObjId
,
2208 digestedData
->ContentInfo
.pszObjId
?
2209 strlen(digestedData
->ContentInfo
.pszObjId
) + 1 : 0);
2210 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
2212 if (digestedData
->ContentInfo
.Content
.cbData
)
2213 CDecodeMsg_DecodeDataContent(msg
,
2214 &digestedData
->ContentInfo
.Content
);
2216 ContextPropertyList_SetProperty(msg
->properties
,
2217 CMSG_CONTENT_PARAM
, NULL
, 0);
2219 ContextPropertyList_SetProperty(msg
->properties
, CMSG_HASH_DATA_PARAM
,
2220 digestedData
->hash
.pbData
, digestedData
->hash
.cbData
);
2221 LocalFree(digestedData
);
2226 static BOOL
CDecodeMsg_DecodeEnvelopedContent(CDecodeMsg
*msg
,
2227 const CRYPT_DER_BLOB
*blob
)
2230 CRYPT_ENVELOPED_DATA
*envelopedData
;
2233 ret
= CRYPT_AsnDecodePKCSEnvelopedData(blob
->pbData
, blob
->cbData
,
2234 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_ENVELOPED_DATA
*)&envelopedData
,
2237 msg
->u
.enveloped_data
.data
= envelopedData
;
2241 static BOOL
CDecodeMsg_DecodeSignedContent(CDecodeMsg
*msg
,
2242 const CRYPT_DER_BLOB
*blob
)
2245 CRYPT_SIGNED_INFO
*signedInfo
;
2248 ret
= CRYPT_AsnDecodeCMSSignedInfo(blob
->pbData
, blob
->cbData
,
2249 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_SIGNED_INFO
*)&signedInfo
,
2252 msg
->u
.signed_data
.info
= signedInfo
;
2256 /* Decodes the content in blob as the type given, and updates the value
2257 * (type, parameters, etc.) of msg based on what blob contains.
2258 * It doesn't just use msg's type, to allow a recursive call from an implicitly
2259 * typed message once the outer content info has been decoded.
2261 static BOOL
CDecodeMsg_DecodeContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
,
2269 if ((ret
= CDecodeMsg_DecodeDataContent(msg
, blob
)))
2270 msg
->type
= CMSG_DATA
;
2273 if ((ret
= CDecodeMsg_DecodeHashedContent(msg
, blob
)))
2274 msg
->type
= CMSG_HASHED
;
2276 case CMSG_ENVELOPED
:
2277 if ((ret
= CDecodeMsg_DecodeEnvelopedContent(msg
, blob
)))
2278 msg
->type
= CMSG_ENVELOPED
;
2281 if ((ret
= CDecodeMsg_DecodeSignedContent(msg
, blob
)))
2282 msg
->type
= CMSG_SIGNED
;
2286 CRYPT_CONTENT_INFO
*info
;
2289 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
,
2290 msg
->msg_data
.pbData
, msg
->msg_data
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
2291 NULL
, &info
, &size
);
2294 if (!strcmp(info
->pszObjId
, szOID_RSA_data
))
2295 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
, CMSG_DATA
);
2296 else if (!strcmp(info
->pszObjId
, szOID_RSA_digestedData
))
2297 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2299 else if (!strcmp(info
->pszObjId
, szOID_RSA_envelopedData
))
2300 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2302 else if (!strcmp(info
->pszObjId
, szOID_RSA_signedData
))
2303 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2307 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2317 static BOOL
CDecodeMsg_FinalizeHashedContent(CDecodeMsg
*msg
,
2318 CRYPT_DER_BLOB
*blob
)
2320 CRYPT_ALGORITHM_IDENTIFIER
*hashAlgoID
= NULL
;
2325 CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, NULL
, &size
);
2326 hashAlgoID
= CryptMemAlloc(size
);
2327 ret
= CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, hashAlgoID
,
2330 algID
= CertOIDToAlgId(hashAlgoID
->pszObjId
);
2331 ret
= CryptCreateHash(msg
->crypt_prov
, algID
, 0, 0, &msg
->u
.hash
);
2334 CRYPT_DATA_BLOB content
;
2336 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2338 /* Unlike for non-detached messages, the data were never stored as
2339 * the content param, but were saved in msg->detached_data instead.
2341 content
.pbData
= msg
->detached_data
.pbData
;
2342 content
.cbData
= msg
->detached_data
.cbData
;
2345 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2346 CMSG_CONTENT_PARAM
, &content
);
2348 ret
= CryptHashData(msg
->u
.hash
, content
.pbData
, content
.cbData
, 0);
2350 CryptMemFree(hashAlgoID
);
2354 static BOOL
CDecodeMsg_FinalizeEnvelopedContent(CDecodeMsg
*msg
,
2355 CRYPT_DER_BLOB
*blob
)
2357 CRYPT_DATA_BLOB
*content
;
2359 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2360 content
= &msg
->detached_data
;
2363 &msg
->u
.enveloped_data
.data
->encryptedContentInfo
.encryptedContent
;
2365 return CRYPT_ConstructBlob(&msg
->u
.enveloped_data
.content
, content
);
2368 static BOOL
CDecodeMsg_FinalizeSignedContent(CDecodeMsg
*msg
,
2369 CRYPT_DER_BLOB
*blob
)
2374 ret
= CSignedMsgData_AllocateHandles(&msg
->u
.signed_data
);
2375 for (i
= 0; ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
2376 ret
= CSignedMsgData_ConstructSignerHandles(&msg
->u
.signed_data
, i
,
2380 CRYPT_DATA_BLOB
*content
;
2382 /* Now that we have all the content, update the hash handles with
2383 * it. If the message is a detached message, the content is stored
2384 * in msg->detached_data rather than in the signed message's
2387 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2388 content
= &msg
->detached_data
;
2390 content
= &msg
->u
.signed_data
.info
->content
.Content
;
2391 if (content
->cbData
)
2393 /* If the message is not detached, have to decode the message's
2394 * content if the type is szOID_RSA_data.
2396 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) &&
2397 !strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2400 CRYPT_DATA_BLOB
*rsa_blob
;
2402 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
,
2403 X509_OCTET_STRING
, content
->pbData
, content
->cbData
,
2404 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &rsa_blob
, &size
);
2407 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2408 rsa_blob
->pbData
, rsa_blob
->cbData
, TRUE
, Verify
);
2409 LocalFree(rsa_blob
);
2413 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2414 content
->pbData
, content
->cbData
, TRUE
, Verify
);
2420 static BOOL
CDecodeMsg_FinalizeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
2427 ret
= CDecodeMsg_FinalizeHashedContent(msg
, blob
);
2429 case CMSG_ENVELOPED
:
2430 ret
= CDecodeMsg_FinalizeEnvelopedContent(msg
, blob
);
2433 ret
= CDecodeMsg_FinalizeSignedContent(msg
, blob
);
2441 static BOOL
CDecodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
2442 DWORD cbData
, BOOL fFinal
)
2444 CDecodeMsg
*msg
= hCryptMsg
;
2447 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
2449 if (msg
->base
.state
== MsgStateFinalized
)
2450 SetLastError(CRYPT_E_MSG_ERROR
);
2451 else if (msg
->base
.streamed
)
2453 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg
, pbData
,
2455 switch (msg
->base
.state
)
2458 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2461 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2462 msg
->base
.state
= MsgStateDataFinalized
;
2464 msg
->base
.state
= MsgStateFinalized
;
2467 msg
->base
.state
= MsgStateUpdated
;
2469 case MsgStateUpdated
:
2470 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2473 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2474 msg
->base
.state
= MsgStateDataFinalized
;
2476 msg
->base
.state
= MsgStateFinalized
;
2479 case MsgStateDataFinalized
:
2480 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2482 msg
->base
.state
= MsgStateFinalized
;
2485 SetLastError(CRYPT_E_MSG_ERROR
);
2492 SetLastError(CRYPT_E_MSG_ERROR
);
2495 switch (msg
->base
.state
)
2498 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2499 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2500 msg
->base
.state
= MsgStateDataFinalized
;
2502 msg
->base
.state
= MsgStateFinalized
;
2504 case MsgStateDataFinalized
:
2505 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2506 msg
->base
.state
= MsgStateFinalized
;
2509 SetLastError(CRYPT_E_MSG_ERROR
);
2513 if (ret
&& fFinal
&&
2514 ((msg
->base
.open_flags
& CMSG_DETACHED_FLAG
&& msg
->base
.state
==
2515 MsgStateDataFinalized
) ||
2516 (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->base
.state
==
2517 MsgStateFinalized
)))
2518 ret
= CDecodeMsg_DecodeContent(msg
, &msg
->msg_data
, msg
->type
);
2519 if (ret
&& msg
->base
.state
== MsgStateFinalized
)
2520 ret
= CDecodeMsg_FinalizeContent(msg
, &msg
->msg_data
);
2524 static BOOL
CDecodeHashMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2525 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2529 switch (dwParamType
)
2531 case CMSG_TYPE_PARAM
:
2532 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2534 case CMSG_HASH_ALGORITHM_PARAM
:
2536 CRYPT_DATA_BLOB blob
;
2538 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2542 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2544 CRYPT_FixUpAlgorithmID(pvData
);
2547 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2550 case CMSG_COMPUTED_HASH_PARAM
:
2551 ret
= CryptGetHashParam(msg
->u
.hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
2555 CRYPT_DATA_BLOB blob
;
2557 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2560 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2562 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2568 /* nextData is an in/out parameter - on input it's the memory location in
2569 * which a copy of in's data should be made, and on output it's the memory
2570 * location immediately after out's copy of in's data.
2572 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB
*out
,
2573 const CRYPT_DATA_BLOB
*in
, LPBYTE
*nextData
)
2575 out
->cbData
= in
->cbData
;
2578 out
->pbData
= *nextData
;
2579 memcpy(out
->pbData
, in
->pbData
, in
->cbData
);
2580 *nextData
+= in
->cbData
;
2584 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
2585 const CRYPT_ALGORITHM_IDENTIFIER
*in
, LPBYTE
*nextData
)
2589 out
->pszObjId
= (LPSTR
)*nextData
;
2590 strcpy(out
->pszObjId
, in
->pszObjId
);
2591 *nextData
+= strlen(out
->pszObjId
) + 1;
2593 CRYPT_CopyBlob(&out
->Parameters
, &in
->Parameters
, nextData
);
2596 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES
*out
,
2597 const CRYPT_ATTRIBUTES
*in
, LPBYTE
*nextData
)
2599 out
->cAttr
= in
->cAttr
;
2604 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2605 out
->rgAttr
= (CRYPT_ATTRIBUTE
*)*nextData
;
2606 *nextData
+= in
->cAttr
* sizeof(CRYPT_ATTRIBUTE
);
2607 for (i
= 0; i
< in
->cAttr
; i
++)
2609 if (in
->rgAttr
[i
].pszObjId
)
2611 out
->rgAttr
[i
].pszObjId
= (LPSTR
)*nextData
;
2612 strcpy(out
->rgAttr
[i
].pszObjId
, in
->rgAttr
[i
].pszObjId
);
2613 *nextData
+= strlen(in
->rgAttr
[i
].pszObjId
) + 1;
2615 if (in
->rgAttr
[i
].cValue
)
2619 out
->rgAttr
[i
].cValue
= in
->rgAttr
[i
].cValue
;
2620 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2621 out
->rgAttr
[i
].rgValue
= (PCRYPT_DATA_BLOB
)*nextData
;
2622 *nextData
+= in
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2623 for (j
= 0; j
< in
->rgAttr
[i
].cValue
; j
++)
2624 CRYPT_CopyBlob(&out
->rgAttr
[i
].rgValue
[j
],
2625 &in
->rgAttr
[i
].rgValue
[j
], nextData
);
2631 static DWORD
CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES
*attr
)
2633 DWORD size
= attr
->cAttr
* sizeof(CRYPT_ATTRIBUTE
), i
, j
;
2635 for (i
= 0; i
< attr
->cAttr
; i
++)
2637 if (attr
->rgAttr
[i
].pszObjId
)
2638 size
+= strlen(attr
->rgAttr
[i
].pszObjId
) + 1;
2640 size
= ALIGN_DWORD_PTR(size
);
2641 size
+= attr
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2642 for (j
= 0; j
< attr
->rgAttr
[i
].cValue
; j
++)
2643 size
+= attr
->rgAttr
[i
].rgValue
[j
].cbData
;
2645 /* align pointer again to be conservative */
2646 size
= ALIGN_DWORD_PTR(size
);
2650 static DWORD
CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB
*keyId
)
2652 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2655 CERT_RDN rdn
= { 1, &attr
};
2656 CERT_NAME_INFO name
= { 1, &rdn
};
2658 attr
.pszObjId
= oid_key_rdn
;
2659 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2660 attr
.Value
.cbData
= keyId
->cbData
;
2661 attr
.Value
.pbData
= keyId
->pbData
;
2662 if (CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, NULL
, &size
))
2663 size
++; /* Only include size of special zero serial number on success */
2667 static BOOL
CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB
*issuer
,
2668 CRYPT_INTEGER_BLOB
*serialNumber
, const CRYPT_DATA_BLOB
*keyId
, DWORD encodedLen
,
2671 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2673 CERT_RDN rdn
= { 1, &attr
};
2674 CERT_NAME_INFO name
= { 1, &rdn
};
2677 /* Encode special zero serial number */
2678 serialNumber
->cbData
= 1;
2679 serialNumber
->pbData
= *nextData
;
2683 issuer
->pbData
= *nextData
;
2684 attr
.pszObjId
= oid_key_rdn
;
2685 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2686 attr
.Value
.cbData
= keyId
->cbData
;
2687 attr
.Value
.pbData
= keyId
->pbData
;
2688 ret
= CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, *nextData
,
2692 *nextData
+= encodedLen
;
2693 issuer
->cbData
= encodedLen
;
2698 static BOOL
CRYPT_CopySignerInfo(void *pvData
, DWORD
*pcbData
,
2699 const CMSG_CMS_SIGNER_INFO
*in
)
2701 DWORD size
= sizeof(CMSG_SIGNER_INFO
), rdnSize
= 0;
2704 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2706 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2708 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2709 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2713 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2716 if (in
->HashAlgorithm
.pszObjId
)
2717 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2718 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2719 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2720 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2721 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2722 size
+= in
->EncryptedHash
.cbData
;
2724 size
= ALIGN_DWORD_PTR(size
);
2725 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2726 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2732 else if (*pcbData
< size
)
2735 SetLastError(ERROR_MORE_DATA
);
2740 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_SIGNER_INFO
);
2741 CMSG_SIGNER_INFO
*out
= pvData
;
2744 out
->dwVersion
= in
->dwVersion
;
2745 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2747 CRYPT_CopyBlob(&out
->Issuer
,
2748 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2749 CRYPT_CopyBlob(&out
->SerialNumber
,
2750 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2753 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2754 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2757 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2759 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2760 &in
->HashEncryptionAlgorithm
, &nextData
);
2761 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2762 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2763 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2764 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2767 TRACE("returning %d\n", ret
);
2771 static BOOL
CRYPT_CopyCMSSignerInfo(void *pvData
, DWORD
*pcbData
,
2772 const CMSG_CMS_SIGNER_INFO
*in
)
2774 DWORD size
= sizeof(CMSG_CMS_SIGNER_INFO
);
2777 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2779 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2781 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2782 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2785 size
+= in
->SignerId
.u
.KeyId
.cbData
;
2786 if (in
->HashAlgorithm
.pszObjId
)
2787 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2788 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2789 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2790 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2791 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2792 size
+= in
->EncryptedHash
.cbData
;
2794 size
= ALIGN_DWORD_PTR(size
);
2795 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2796 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2802 else if (*pcbData
< size
)
2805 SetLastError(ERROR_MORE_DATA
);
2810 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_CMS_SIGNER_INFO
);
2811 CMSG_CMS_SIGNER_INFO
*out
= pvData
;
2813 out
->dwVersion
= in
->dwVersion
;
2814 out
->SignerId
.dwIdChoice
= in
->SignerId
.dwIdChoice
;
2815 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2817 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
2818 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2819 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
2820 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2823 CRYPT_CopyBlob(&out
->SignerId
.u
.KeyId
, &in
->SignerId
.u
.KeyId
, &nextData
);
2824 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2826 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2827 &in
->HashEncryptionAlgorithm
, &nextData
);
2828 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2829 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2830 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2831 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2834 TRACE("returning %d\n", ret
);
2838 static BOOL
CRYPT_CopySignerCertInfo(void *pvData
, DWORD
*pcbData
,
2839 const CMSG_CMS_SIGNER_INFO
*in
)
2841 DWORD size
= sizeof(CERT_INFO
), rdnSize
= 0;
2844 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2846 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2848 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2849 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2853 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2861 else if (*pcbData
< size
)
2864 SetLastError(ERROR_MORE_DATA
);
2869 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2870 CERT_INFO
*out
= pvData
;
2872 memset(out
, 0, sizeof(CERT_INFO
));
2873 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2875 CRYPT_CopyBlob(&out
->Issuer
,
2876 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2877 CRYPT_CopyBlob(&out
->SerialNumber
,
2878 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2882 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2883 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2885 TRACE("returning %d\n", ret
);
2889 static BOOL
CRYPT_CopyRecipientInfo(void *pvData
, DWORD
*pcbData
,
2890 const CERT_ISSUER_SERIAL_NUMBER
*in
)
2892 DWORD size
= sizeof(CERT_INFO
);
2895 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2897 size
+= in
->SerialNumber
.cbData
;
2898 size
+= in
->Issuer
.cbData
;
2904 else if (*pcbData
< size
)
2907 SetLastError(ERROR_MORE_DATA
);
2912 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2913 CERT_INFO
*out
= pvData
;
2915 CRYPT_CopyBlob(&out
->SerialNumber
, &in
->SerialNumber
, &nextData
);
2916 CRYPT_CopyBlob(&out
->Issuer
, &in
->Issuer
, &nextData
);
2919 TRACE("returning %d\n", ret
);
2923 static BOOL
CDecodeEnvelopedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2924 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2928 switch (dwParamType
)
2930 case CMSG_TYPE_PARAM
:
2931 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2933 case CMSG_CONTENT_PARAM
:
2934 if (msg
->u
.enveloped_data
.data
)
2935 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2936 msg
->u
.enveloped_data
.content
.pbData
,
2937 msg
->u
.enveloped_data
.content
.cbData
);
2939 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2941 case CMSG_RECIPIENT_COUNT_PARAM
:
2942 if (msg
->u
.enveloped_data
.data
)
2943 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2944 &msg
->u
.enveloped_data
.data
->cRecipientInfo
, sizeof(DWORD
));
2946 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2948 case CMSG_RECIPIENT_INFO_PARAM
:
2949 if (msg
->u
.enveloped_data
.data
)
2951 if (dwIndex
< msg
->u
.enveloped_data
.data
->cRecipientInfo
)
2953 PCMSG_KEY_TRANS_RECIPIENT_INFO recipientInfo
=
2954 &msg
->u
.enveloped_data
.data
->rgRecipientInfo
[dwIndex
];
2956 ret
= CRYPT_CopyRecipientInfo(pvData
, pcbData
,
2957 &recipientInfo
->RecipientId
.u
.IssuerSerialNumber
);
2960 SetLastError(CRYPT_E_INVALID_INDEX
);
2963 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2966 FIXME("unimplemented for %d\n", dwParamType
);
2967 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2972 static BOOL
CDecodeSignedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2973 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2977 switch (dwParamType
)
2979 case CMSG_TYPE_PARAM
:
2980 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2982 case CMSG_CONTENT_PARAM
:
2983 if (msg
->u
.signed_data
.info
)
2985 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2988 CRYPT_DATA_BLOB
*blob
;
2991 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
2992 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
2993 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
2994 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &blob
, &size
);
2997 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
->pbData
,
3003 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3004 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
3005 msg
->u
.signed_data
.info
->content
.Content
.cbData
);
3008 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3010 case CMSG_INNER_CONTENT_TYPE_PARAM
:
3011 if (msg
->u
.signed_data
.info
)
3012 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3013 msg
->u
.signed_data
.info
->content
.pszObjId
,
3014 strlen(msg
->u
.signed_data
.info
->content
.pszObjId
) + 1);
3016 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3018 case CMSG_SIGNER_COUNT_PARAM
:
3019 if (msg
->u
.signed_data
.info
)
3020 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3021 &msg
->u
.signed_data
.info
->cSignerInfo
, sizeof(DWORD
));
3023 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3025 case CMSG_SIGNER_INFO_PARAM
:
3026 if (msg
->u
.signed_data
.info
)
3028 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3029 SetLastError(CRYPT_E_INVALID_INDEX
);
3031 ret
= CRYPT_CopySignerInfo(pvData
, pcbData
,
3032 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3035 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3037 case CMSG_SIGNER_CERT_INFO_PARAM
:
3038 if (msg
->u
.signed_data
.info
)
3040 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3041 SetLastError(CRYPT_E_INVALID_INDEX
);
3043 ret
= CRYPT_CopySignerCertInfo(pvData
, pcbData
,
3044 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3047 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3049 case CMSG_CERT_COUNT_PARAM
:
3050 if (msg
->u
.signed_data
.info
)
3051 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3052 &msg
->u
.signed_data
.info
->cCertEncoded
, sizeof(DWORD
));
3054 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3056 case CMSG_CERT_PARAM
:
3057 if (msg
->u
.signed_data
.info
)
3059 if (dwIndex
>= msg
->u
.signed_data
.info
->cCertEncoded
)
3060 SetLastError(CRYPT_E_INVALID_INDEX
);
3062 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3063 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].pbData
,
3064 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].cbData
);
3067 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3069 case CMSG_CRL_COUNT_PARAM
:
3070 if (msg
->u
.signed_data
.info
)
3071 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3072 &msg
->u
.signed_data
.info
->cCrlEncoded
, sizeof(DWORD
));
3074 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3076 case CMSG_CRL_PARAM
:
3077 if (msg
->u
.signed_data
.info
)
3079 if (dwIndex
>= msg
->u
.signed_data
.info
->cCrlEncoded
)
3080 SetLastError(CRYPT_E_INVALID_INDEX
);
3082 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3083 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].pbData
,
3084 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].cbData
);
3087 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3089 case CMSG_COMPUTED_HASH_PARAM
:
3090 if (msg
->u
.signed_data
.info
)
3092 if (dwIndex
>= msg
->u
.signed_data
.cSignerHandle
)
3093 SetLastError(CRYPT_E_INVALID_INDEX
);
3095 ret
= CryptGetHashParam(
3096 msg
->u
.signed_data
.signerHandles
[dwIndex
].contentHash
,
3097 HP_HASHVAL
, pvData
, pcbData
, 0);
3100 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3102 case CMSG_ENCODED_SIGNER
:
3103 if (msg
->u
.signed_data
.info
)
3105 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3106 SetLastError(CRYPT_E_INVALID_INDEX
);
3108 ret
= CryptEncodeObjectEx(
3109 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, CMS_SIGNER_INFO
,
3110 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
], 0, NULL
,
3114 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3116 case CMSG_ATTR_CERT_COUNT_PARAM
:
3117 if (msg
->u
.signed_data
.info
)
3119 DWORD attrCertCount
= 0;
3121 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3122 &attrCertCount
, sizeof(DWORD
));
3125 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3127 case CMSG_ATTR_CERT_PARAM
:
3128 if (msg
->u
.signed_data
.info
)
3129 SetLastError(CRYPT_E_INVALID_INDEX
);
3131 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3133 case CMSG_CMS_SIGNER_INFO_PARAM
:
3134 if (msg
->u
.signed_data
.info
)
3136 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3137 SetLastError(CRYPT_E_INVALID_INDEX
);
3139 ret
= CRYPT_CopyCMSSignerInfo(pvData
, pcbData
,
3140 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3143 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3146 FIXME("unimplemented for %d\n", dwParamType
);
3147 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3152 static BOOL
CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
3153 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3155 CDecodeMsg
*msg
= hCryptMsg
;
3161 ret
= CDecodeHashMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3164 case CMSG_ENVELOPED
:
3165 ret
= CDecodeEnvelopedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3169 ret
= CDecodeSignedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3173 switch (dwParamType
)
3175 case CMSG_TYPE_PARAM
:
3176 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
,
3181 CRYPT_DATA_BLOB blob
;
3183 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
3186 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
,
3189 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3196 static BOOL
CDecodeHashMsg_VerifyHash(CDecodeMsg
*msg
)
3199 CRYPT_DATA_BLOB hashBlob
;
3201 ret
= ContextPropertyList_FindProperty(msg
->properties
,
3202 CMSG_HASH_DATA_PARAM
, &hashBlob
);
3205 DWORD computedHashSize
= 0;
3207 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
,
3209 if (hashBlob
.cbData
== computedHashSize
)
3211 LPBYTE computedHash
= CryptMemAlloc(computedHashSize
);
3215 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
3216 computedHash
, &computedHashSize
);
3219 if (memcmp(hashBlob
.pbData
, computedHash
, hashBlob
.cbData
))
3221 SetLastError(CRYPT_E_HASH_VALUE
);
3225 CryptMemFree(computedHash
);
3229 SetLastError(ERROR_OUTOFMEMORY
);
3235 SetLastError(CRYPT_E_HASH_VALUE
);
3242 static BOOL
CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg
*msg
,
3243 HCRYPTPROV prov
, DWORD signerIndex
, PCERT_PUBLIC_KEY_INFO keyInfo
)
3249 prov
= msg
->crypt_prov
;
3250 ret
= CryptImportPublicKeyInfo(prov
, X509_ASN_ENCODING
, keyInfo
, &key
);
3254 CRYPT_HASH_BLOB reversedHash
;
3256 if (msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
)
3257 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].authAttrHash
;
3259 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].contentHash
;
3260 ret
= CRYPT_ConstructBlob(&reversedHash
,
3261 &msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].EncryptedHash
);
3264 CRYPT_ReverseBytes(&reversedHash
);
3265 ret
= CryptVerifySignatureW(hash
, reversedHash
.pbData
,
3266 reversedHash
.cbData
, key
, NULL
, 0);
3267 CryptMemFree(reversedHash
.pbData
);
3269 CryptDestroyKey(key
);
3274 static BOOL
CDecodeSignedMsg_VerifySignature(CDecodeMsg
*msg
, PCERT_INFO info
)
3279 if (!msg
->u
.signed_data
.signerHandles
)
3281 SetLastError(NTE_BAD_SIGNATURE
);
3284 for (i
= 0; !ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
3286 PCMSG_CMS_SIGNER_INFO signerInfo
=
3287 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
];
3289 if (signerInfo
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
3291 ret
= CertCompareCertificateName(X509_ASN_ENCODING
,
3292 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
3296 ret
= CertCompareIntegerBlob(
3297 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
3298 &info
->SerialNumber
);
3305 FIXME("signer %d: unimplemented for key id\n", i
);
3309 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, 0, i
,
3310 &info
->SubjectPublicKeyInfo
);
3312 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3317 static BOOL
CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg
*msg
,
3318 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para
)
3322 if (para
->cbSize
!= sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
))
3323 SetLastError(ERROR_INVALID_PARAMETER
);
3324 else if (para
->dwSignerIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3325 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3326 else if (!msg
->u
.signed_data
.signerHandles
)
3327 SetLastError(NTE_BAD_SIGNATURE
);
3330 switch (para
->dwSignerType
)
3332 case CMSG_VERIFY_SIGNER_PUBKEY
:
3333 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
,
3334 para
->hCryptProv
, para
->dwSignerIndex
, para
->pvSigner
);
3336 case CMSG_VERIFY_SIGNER_CERT
:
3338 PCCERT_CONTEXT cert
= para
->pvSigner
;
3340 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, para
->hCryptProv
,
3341 para
->dwSignerIndex
, &cert
->pCertInfo
->SubjectPublicKeyInfo
);
3345 FIXME("unimplemented for signer type %d\n", para
->dwSignerType
);
3346 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3352 static BOOL WINAPI
CRYPT_ImportKeyTrans(
3353 PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm
,
3354 PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara
, DWORD dwFlags
,
3355 void *pvReserved
, HCRYPTKEY
*phContentEncryptKey
)
3360 ret
= CryptGetUserKey(pKeyTransDecryptPara
->hCryptProv
,
3361 pKeyTransDecryptPara
->dwKeySpec
? pKeyTransDecryptPara
->dwKeySpec
:
3362 AT_KEYEXCHANGE
, &key
);
3365 CMSG_KEY_TRANS_RECIPIENT_INFO
*info
=
3366 &pKeyTransDecryptPara
->pKeyTrans
[pKeyTransDecryptPara
->dwRecipientIndex
];
3367 CRYPT_DATA_BLOB
*encryptedKey
= &info
->EncryptedKey
;
3368 DWORD size
= encryptedKey
->cbData
+ sizeof(BLOBHEADER
) + sizeof(ALG_ID
);
3369 BYTE
*keyBlob
= CryptMemAlloc(size
);
3373 DWORD i
, k
= size
- 1;
3374 BLOBHEADER
*blobHeader
= (BLOBHEADER
*)keyBlob
;
3375 ALG_ID
*algID
= (ALG_ID
*)(keyBlob
+ sizeof(BLOBHEADER
));
3377 blobHeader
->bType
= SIMPLEBLOB
;
3378 blobHeader
->bVersion
= CUR_BLOB_VERSION
;
3379 blobHeader
->reserved
= 0;
3380 blobHeader
->aiKeyAlg
= CertOIDToAlgId(
3381 pContentEncryptionAlgorithm
->pszObjId
);
3382 *algID
= CertOIDToAlgId(info
->KeyEncryptionAlgorithm
.pszObjId
);
3383 for (i
= 0; i
< encryptedKey
->cbData
; ++i
, --k
)
3384 keyBlob
[k
] = encryptedKey
->pbData
[i
];
3386 ret
= CryptImportKey(pKeyTransDecryptPara
->hCryptProv
, keyBlob
,
3387 size
, key
, 0, phContentEncryptKey
);
3388 CryptMemFree(keyBlob
);
3392 CryptDestroyKey(key
);
3397 static BOOL
CRYPT_ImportEncryptedKey(PCRYPT_ALGORITHM_IDENTIFIER contEncrAlg
,
3398 PCMSG_CTRL_DECRYPT_PARA para
, PCMSG_KEY_TRANS_RECIPIENT_INFO info
,
3401 static HCRYPTOIDFUNCSET set
= NULL
;
3402 PFN_CMSG_IMPORT_KEY_TRANS importKeyFunc
= NULL
;
3403 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3404 CMSG_CTRL_KEY_TRANS_DECRYPT_PARA decryptPara
;
3407 memset(&decryptPara
, 0, sizeof(decryptPara
));
3408 decryptPara
.cbSize
= sizeof(decryptPara
);
3409 decryptPara
.hCryptProv
= para
->hCryptProv
;
3410 decryptPara
.dwKeySpec
= para
->dwKeySpec
;
3411 decryptPara
.pKeyTrans
= info
;
3412 decryptPara
.dwRecipientIndex
= para
->dwRecipientIndex
;
3415 set
= CryptInitOIDFunctionSet(CMSG_OID_IMPORT_KEY_TRANS_FUNC
, 0);
3416 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
, contEncrAlg
->pszObjId
, 0,
3417 (void **)&importKeyFunc
, &hFunc
);
3419 importKeyFunc
= CRYPT_ImportKeyTrans
;
3420 ret
= importKeyFunc(contEncrAlg
, &decryptPara
, 0, NULL
, key
);
3422 CryptFreeOIDFunctionAddress(hFunc
, 0);
3426 static BOOL
CDecodeEnvelopedMsg_CrtlDecrypt(CDecodeMsg
*msg
,
3427 PCMSG_CTRL_DECRYPT_PARA para
)
3430 CEnvelopedDecodeMsg
*enveloped_data
= &msg
->u
.enveloped_data
;
3431 CRYPT_ENVELOPED_DATA
*data
= enveloped_data
->data
;
3433 if (para
->cbSize
!= sizeof(CMSG_CTRL_DECRYPT_PARA
))
3434 SetLastError(E_INVALIDARG
);
3436 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3437 else if (para
->dwRecipientIndex
>= data
->cRecipientInfo
)
3438 SetLastError(CRYPT_E_INVALID_INDEX
);
3439 else if (enveloped_data
->decrypted
)
3440 SetLastError(CRYPT_E_ALREADY_DECRYPTED
);
3441 else if (!para
->hCryptProv
)
3442 SetLastError(ERROR_INVALID_PARAMETER
);
3443 else if (enveloped_data
->content
.cbData
)
3447 ret
= CRYPT_ImportEncryptedKey(
3448 &data
->encryptedContentInfo
.contentEncryptionAlgorithm
, para
,
3449 data
->rgRecipientInfo
, &key
);
3452 ret
= CryptDecrypt(key
, 0, TRUE
, 0, enveloped_data
->content
.pbData
,
3453 &enveloped_data
->content
.cbData
);
3454 CryptDestroyKey(key
);
3460 enveloped_data
->decrypted
= TRUE
;
3464 static BOOL
CDecodeMsg_Control(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3465 DWORD dwCtrlType
, const void *pvCtrlPara
)
3467 CDecodeMsg
*msg
= hCryptMsg
;
3472 case CMSG_CTRL_VERIFY_SIGNATURE
:
3476 ret
= CDecodeSignedMsg_VerifySignature(msg
, (PCERT_INFO
)pvCtrlPara
);
3479 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3482 case CMSG_CTRL_DECRYPT
:
3485 case CMSG_ENVELOPED
:
3486 ret
= CDecodeEnvelopedMsg_CrtlDecrypt(msg
,
3487 (PCMSG_CTRL_DECRYPT_PARA
)pvCtrlPara
);
3488 if (ret
&& (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
))
3489 msg
->u
.enveloped_data
.crypt_prov
=
3490 ((PCMSG_CTRL_DECRYPT_PARA
)pvCtrlPara
)->hCryptProv
;
3493 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3496 case CMSG_CTRL_VERIFY_HASH
:
3500 ret
= CDecodeHashMsg_VerifyHash(msg
);
3503 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3506 case CMSG_CTRL_VERIFY_SIGNATURE_EX
:
3510 ret
= CDecodeSignedMsg_VerifySignatureEx(msg
,
3511 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
)pvCtrlPara
);
3514 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3518 SetLastError(CRYPT_E_CONTROL_TYPE
);
3523 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
3524 DWORD dwMsgType
, HCRYPTPROV_LEGACY hCryptProv
, PCERT_INFO pRecipientInfo
,
3525 PCMSG_STREAM_INFO pStreamInfo
)
3529 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType
,
3530 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
3532 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
3534 SetLastError(E_INVALIDARG
);
3537 msg
= CryptMemAlloc(sizeof(CDecodeMsg
));
3540 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
3541 CDecodeMsg_Close
, CDecodeMsg_GetParam
, CDecodeMsg_Update
,
3542 CDecodeMsg_Control
);
3543 msg
->type
= dwMsgType
;
3545 msg
->crypt_prov
= hCryptProv
;
3548 msg
->crypt_prov
= CRYPT_GetDefaultProvider();
3549 msg
->base
.open_flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
3551 memset(&msg
->u
, 0, sizeof(msg
->u
));
3552 msg
->msg_data
.cbData
= 0;
3553 msg
->msg_data
.pbData
= NULL
;
3554 msg
->detached_data
.cbData
= 0;
3555 msg
->detached_data
.pbData
= NULL
;
3556 msg
->properties
= ContextPropertyList_Create();
3561 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
3563 TRACE("(%p)\n", hCryptMsg
);
3567 CryptMsgBase
*msg
= hCryptMsg
;
3569 InterlockedIncrement(&msg
->ref
);
3574 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
3576 TRACE("(%p)\n", hCryptMsg
);
3580 CryptMsgBase
*msg
= hCryptMsg
;
3582 if (InterlockedDecrement(&msg
->ref
) == 0)
3584 TRACE("freeing %p\n", msg
);
3593 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
3594 DWORD cbData
, BOOL fFinal
)
3596 CryptMsgBase
*msg
= hCryptMsg
;
3598 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
3600 return msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
3603 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
3604 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3606 CryptMsgBase
*msg
= hCryptMsg
;
3608 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
3610 return msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);
3613 BOOL WINAPI
CryptMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3614 DWORD dwCtrlType
, const void *pvCtrlPara
)
3616 CryptMsgBase
*msg
= hCryptMsg
;
3618 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
,
3620 return msg
->control(hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
3623 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
3624 DWORD dwSignerIndex
)
3626 CERT_INFO
*certInfo
= NULL
;
3629 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
3632 certInfo
= CryptMemAlloc(size
);
3635 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
3636 dwSignerIndex
, certInfo
, &size
))
3638 CryptMemFree(certInfo
);
3646 BOOL WINAPI
CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg
, DWORD cSignerStore
,
3647 HCERTSTORE
*rghSignerStore
, DWORD dwFlags
, PCCERT_CONTEXT
*ppSigner
,
3648 DWORD
*pdwSignerIndex
)
3651 DWORD i
, signerIndex
= 0;
3652 PCCERT_CONTEXT signerCert
= NULL
;
3655 TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg
, cSignerStore
,
3656 rghSignerStore
, dwFlags
, ppSigner
, pdwSignerIndex
);
3658 /* Clear output parameters */
3661 if (pdwSignerIndex
&& !(dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
))
3662 *pdwSignerIndex
= 0;
3664 /* Create store to search for signer certificates */
3665 store
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
3666 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
3667 if (!(dwFlags
& CMSG_TRUSTED_SIGNER_FLAG
))
3669 HCERTSTORE msgStore
= CertOpenStore(CERT_STORE_PROV_MSG
, 0, 0, 0,
3672 CertAddStoreToCollection(store
, msgStore
, 0, 0);
3673 CertCloseStore(msgStore
, 0);
3675 for (i
= 0; i
< cSignerStore
; i
++)
3676 CertAddStoreToCollection(store
, rghSignerStore
[i
], 0, 0);
3678 /* Find signer cert */
3679 if (dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
)
3681 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3686 signerIndex
= *pdwSignerIndex
;
3687 signerCert
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
,
3688 0, CERT_FIND_SUBJECT_CERT
, signer
, NULL
);
3689 CryptMemFree(signer
);
3694 DWORD count
, size
= sizeof(count
);
3696 if (CryptMsgGetParam(hCryptMsg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
,
3699 for (i
= 0; !signerCert
&& i
< count
; i
++)
3701 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3706 signerCert
= CertFindCertificateInStore(store
,
3707 X509_ASN_ENCODING
, 0, CERT_FIND_SUBJECT_CERT
, signer
,
3711 CryptMemFree(signer
);
3716 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER
);
3720 if (!(dwFlags
& CMSG_SIGNER_ONLY_FLAG
))
3721 ret
= CryptMsgControl(hCryptMsg
, 0, CMSG_CTRL_VERIFY_SIGNATURE
,
3722 signerCert
->pCertInfo
);
3728 *ppSigner
= CertDuplicateCertificateContext(signerCert
);
3730 *pdwSignerIndex
= signerIndex
;
3732 CertFreeCertificateContext(signerCert
);
3735 CertCloseStore(store
, 0);
3739 BOOL WINAPI
CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv
,
3740 DWORD dwEncodingType
, PBYTE pbSignerInfo
, DWORD cbSignerInfo
,
3741 PBYTE pbSignerInfoCountersignature
, DWORD cbSignerInfoCountersignature
,
3742 DWORD dwSignerType
, void *pvSigner
, DWORD dwFlags
, void *pvReserved
)
3744 FIXME("(%08lx, %08x, %p, %d, %p, %d, %d, %p, %08x, %p): stub\n", hCryptProv
,
3745 dwEncodingType
, pbSignerInfo
, cbSignerInfo
, pbSignerInfoCountersignature
,
3746 cbSignerInfoCountersignature
, dwSignerType
, pvSigner
, dwFlags
, pvReserved
);
3750 BOOL WINAPI
CryptMsgEncodeAndSignCTL(DWORD dwMsgEncodingType
,
3751 PCTL_INFO pCtlInfo
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3752 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3758 TRACE("(%08x, %p, %p, %08x, %p, %p)\n", dwMsgEncodingType
, pCtlInfo
,
3759 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3763 FIXME("unimplemented for flags %08x\n", dwFlags
);
3766 if ((ret
= CryptEncodeObjectEx(dwMsgEncodingType
, PKCS_CTL
, pCtlInfo
,
3767 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &pbCtlContent
, &cbCtlContent
)))
3769 ret
= CryptMsgSignCTL(dwMsgEncodingType
, pbCtlContent
, cbCtlContent
,
3770 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3771 LocalFree(pbCtlContent
);
3776 BOOL WINAPI
CryptMsgSignCTL(DWORD dwMsgEncodingType
, BYTE
*pbCtlContent
,
3777 DWORD cbCtlContent
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3778 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3780 static char oid_ctl
[] = szOID_CTL
;
3784 TRACE("(%08x, %p, %d, %p, %08x, %p, %p)\n", dwMsgEncodingType
,
3785 pbCtlContent
, cbCtlContent
, pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3789 FIXME("unimplemented for flags %08x\n", dwFlags
);
3792 msg
= CryptMsgOpenToEncode(dwMsgEncodingType
, 0, CMSG_SIGNED
, pSignInfo
,
3796 ret
= CryptMsgUpdate(msg
, pbCtlContent
, cbCtlContent
, TRUE
);
3798 ret
= CryptMsgGetParam(msg
, CMSG_CONTENT_PARAM
, 0, pbEncoded
,