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
19 #include "crypt32_private.h"
21 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
23 /* Called when a message's ref count reaches zero. Free any message-specific
26 typedef void (*CryptMsgCloseFunc
)(HCRYPTMSG msg
);
28 typedef BOOL (*CryptMsgGetParamFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
29 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
);
31 typedef BOOL (*CryptMsgUpdateFunc
)(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
32 DWORD cbData
, BOOL fFinal
);
34 typedef BOOL (*CryptMsgControlFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
35 DWORD dwCtrlType
, const void *pvCtrlPara
);
37 static BOOL
CRYPT_DefaultMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
38 DWORD dwCtrlType
, const void *pvCtrlPara
)
40 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
41 SetLastError(E_INVALIDARG
);
45 typedef enum _CryptMsgState
{
48 MsgStateDataFinalized
,
52 typedef struct _CryptMsgBase
57 CMSG_STREAM_INFO stream_info
;
59 CryptMsgCloseFunc close
;
60 CryptMsgUpdateFunc update
;
61 CryptMsgGetParamFunc get_param
;
62 CryptMsgControlFunc control
;
65 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
66 PCMSG_STREAM_INFO pStreamInfo
, CryptMsgCloseFunc close
,
67 CryptMsgGetParamFunc get_param
, CryptMsgUpdateFunc update
,
68 CryptMsgControlFunc control
)
71 msg
->open_flags
= dwFlags
;
75 msg
->stream_info
= *pStreamInfo
;
79 msg
->streamed
= FALSE
;
80 memset(&msg
->stream_info
, 0, sizeof(msg
->stream_info
));
83 msg
->get_param
= get_param
;
85 msg
->control
= control
;
86 msg
->state
= MsgStateInit
;
89 typedef struct _CDataEncodeMsg
92 DWORD bare_content_len
;
96 static const BYTE empty_data_content
[] = { 0x04,0x00 };
98 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
100 CDataEncodeMsg
*msg
= hCryptMsg
;
102 if (msg
->bare_content
!= empty_data_content
)
103 LocalFree(msg
->bare_content
);
106 static BOOL WINAPI
CRYPT_EncodeContentLength(DWORD dwCertEncodingType
,
107 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
108 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
110 DWORD dataLen
= *(DWORD
*)pvStructInfo
;
114 /* Trick: report bytes needed based on total message length, even though
115 * the message isn't available yet. The caller will use the length
116 * reported here to encode its length.
118 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
120 *pcbEncoded
= 1 + lenBytes
+ dataLen
;
123 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
124 pcbEncoded
, 1 + lenBytes
)))
126 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
127 pbEncoded
= *(BYTE
**)pbEncoded
;
128 *pbEncoded
++ = ASN_OCTETSTRING
;
129 CRYPT_EncodeLen(dataLen
, pbEncoded
,
136 static BOOL
CRYPT_EncodeDataContentInfoHeader(const CDataEncodeMsg
*msg
,
137 CRYPT_DATA_BLOB
*header
)
141 if (msg
->base
.streamed
&& msg
->base
.stream_info
.cbContent
== 0xffffffff)
143 static const BYTE headerValue
[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,
144 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80 };
146 header
->pbData
= LocalAlloc(0, sizeof(headerValue
));
149 header
->cbData
= sizeof(headerValue
);
150 memcpy(header
->pbData
, headerValue
, sizeof(headerValue
));
158 struct AsnConstructedItem constructed
= { 0,
159 &msg
->base
.stream_info
.cbContent
, CRYPT_EncodeContentLength
};
160 struct AsnEncodeSequenceItem items
[2] = {
161 { szOID_RSA_data
, CRYPT_AsnEncodeOid
, 0 },
162 { &constructed
, CRYPT_AsnEncodeConstructed
, 0 },
165 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
166 sizeof(items
) / sizeof(items
[0]), CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
167 (LPBYTE
)&header
->pbData
, &header
->cbData
);
170 /* Trick: subtract the content length from the reported length,
171 * as the actual content hasn't come yet.
173 header
->cbData
-= msg
->base
.stream_info
.cbContent
;
179 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
180 DWORD cbData
, BOOL fFinal
)
182 CDataEncodeMsg
*msg
= hCryptMsg
;
185 if (msg
->base
.state
== MsgStateFinalized
)
186 SetLastError(CRYPT_E_MSG_ERROR
);
187 else if (msg
->base
.streamed
)
191 if (msg
->base
.state
!= MsgStateUpdated
)
193 CRYPT_DATA_BLOB header
;
195 ret
= CRYPT_EncodeDataContentInfoHeader(msg
, &header
);
198 ret
= msg
->base
.stream_info
.pfnStreamOutput(
199 msg
->base
.stream_info
.pvArg
, header
.pbData
, header
.cbData
,
201 LocalFree(header
.pbData
);
204 /* Curiously, every indefinite-length streamed update appears to
205 * get its own tag and length, regardless of fFinal.
207 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
212 ret
= CRYPT_EncodeContentLength(X509_ASN_ENCODING
, NULL
,
213 &cbData
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (BYTE
*)&header
,
217 ret
= msg
->base
.stream_info
.pfnStreamOutput(
218 msg
->base
.stream_info
.pvArg
, header
, headerLen
,
225 ret
= msg
->base
.stream_info
.pfnStreamOutput(
226 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
228 msg
->base
.state
= MsgStateUpdated
;
232 msg
->base
.state
= MsgStateFinalized
;
233 if (msg
->base
.stream_info
.cbContent
== 0xffffffff)
235 BYTE indefinite_trailer
[6] = { 0 };
237 ret
= msg
->base
.stream_info
.pfnStreamOutput(
238 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
,
241 ret
= msg
->base
.stream_info
.pfnStreamOutput(
242 msg
->base
.stream_info
.pvArg
, indefinite_trailer
,
243 sizeof(indefinite_trailer
), TRUE
);
246 ret
= msg
->base
.stream_info
.pfnStreamOutput(
247 msg
->base
.stream_info
.pvArg
, (BYTE
*)pbData
, cbData
, TRUE
);
252 SetLastError(STATUS_ACCESS_VIOLATION
);
261 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
262 SetLastError(E_INVALIDARG
);
264 SetLastError(CRYPT_E_MSG_ERROR
);
268 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
270 msg
->base
.state
= MsgStateFinalized
;
271 /* non-streamed data messages don't allow non-final updates,
272 * don't bother checking whether data already exist, they can't.
274 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
275 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
276 &msg
->bare_content_len
);
282 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
289 else if (*pcbData
< len
)
292 SetLastError(ERROR_MORE_DATA
);
298 memcpy(pvData
, src
, len
);
303 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
304 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
306 CDataEncodeMsg
*msg
= hCryptMsg
;
311 case CMSG_CONTENT_PARAM
:
312 if (msg
->base
.streamed
)
313 SetLastError(E_INVALIDARG
);
316 CRYPT_CONTENT_INFO info
;
317 char rsa_data
[] = "1.2.840.113549.1.7.1";
319 info
.pszObjId
= rsa_data
;
320 info
.Content
.cbData
= msg
->bare_content_len
;
321 info
.Content
.pbData
= msg
->bare_content
;
322 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
326 case CMSG_BARE_CONTENT_PARAM
:
327 if (msg
->base
.streamed
)
328 SetLastError(E_INVALIDARG
);
330 ret
= CRYPT_CopyParam(pvData
, pcbData
, msg
->bare_content
,
331 msg
->bare_content_len
);
334 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
339 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
340 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
346 SetLastError(E_INVALIDARG
);
349 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
352 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
353 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
,
354 CRYPT_DefaultMsgControl
);
355 msg
->bare_content_len
= sizeof(empty_data_content
);
356 msg
->bare_content
= (LPBYTE
)empty_data_content
;
361 typedef struct _CHashEncodeMsg
366 CRYPT_DATA_BLOB data
;
369 static void CHashEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
371 CHashEncodeMsg
*msg
= hCryptMsg
;
373 CryptMemFree(msg
->data
.pbData
);
374 CryptDestroyHash(msg
->hash
);
375 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
376 CryptReleaseContext(msg
->prov
, 0);
379 static BOOL
CRYPT_EncodePKCSDigestedData(CHashEncodeMsg
*msg
, void *pvData
,
384 DWORD size
= sizeof(algID
);
386 ret
= CryptGetHashParam(msg
->hash
, HP_ALGID
, (BYTE
*)&algID
, &size
, 0);
389 CRYPT_DIGESTED_DATA digestedData
= { 0 };
390 char oid_rsa_data
[] = szOID_RSA_data
;
392 digestedData
.version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
393 digestedData
.DigestAlgorithm
.pszObjId
= (LPSTR
)CertAlgIdToOID(algID
);
394 /* FIXME: what about digestedData.DigestAlgorithm.Parameters? */
395 /* Quirk: OID is only encoded messages if an update has happened */
396 if (msg
->base
.state
!= MsgStateInit
)
397 digestedData
.ContentInfo
.pszObjId
= oid_rsa_data
;
398 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->data
.cbData
)
400 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &msg
->data
,
401 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
402 (LPBYTE
)&digestedData
.ContentInfo
.Content
.pbData
,
403 &digestedData
.ContentInfo
.Content
.cbData
);
405 if (msg
->base
.state
== MsgStateFinalized
)
407 size
= sizeof(DWORD
);
408 ret
= CryptGetHashParam(msg
->hash
, HP_HASHSIZE
,
409 (LPBYTE
)&digestedData
.hash
.cbData
, &size
, 0);
412 digestedData
.hash
.pbData
= CryptMemAlloc(
413 digestedData
.hash
.cbData
);
414 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
,
415 digestedData
.hash
.pbData
, &digestedData
.hash
.cbData
, 0);
419 ret
= CRYPT_AsnEncodePKCSDigestedData(&digestedData
, pvData
,
421 CryptMemFree(digestedData
.hash
.pbData
);
422 LocalFree(digestedData
.ContentInfo
.Content
.pbData
);
427 static BOOL
CHashEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
428 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
430 CHashEncodeMsg
*msg
= hCryptMsg
;
433 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
438 case CMSG_BARE_CONTENT_PARAM
:
439 if (msg
->base
.streamed
)
440 SetLastError(E_INVALIDARG
);
442 ret
= CRYPT_EncodePKCSDigestedData(msg
, pvData
, pcbData
);
444 case CMSG_CONTENT_PARAM
:
446 CRYPT_CONTENT_INFO info
;
448 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
449 &info
.Content
.cbData
);
452 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
453 if (info
.Content
.pbData
)
455 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
456 info
.Content
.pbData
, &info
.Content
.cbData
);
459 char oid_rsa_hashed
[] = szOID_RSA_hashedData
;
461 info
.pszObjId
= oid_rsa_hashed
;
462 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
463 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
465 CryptMemFree(info
.Content
.pbData
);
472 case CMSG_COMPUTED_HASH_PARAM
:
473 ret
= CryptGetHashParam(msg
->hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
475 case CMSG_VERSION_PARAM
:
476 if (msg
->base
.state
!= MsgStateFinalized
)
477 SetLastError(CRYPT_E_MSG_ERROR
);
480 DWORD version
= CMSG_HASHED_DATA_PKCS_1_5_VERSION
;
482 /* Since the data are always encoded as octets, the version is
483 * always 0 (see rfc3852, section 7)
485 ret
= CRYPT_CopyParam(pvData
, pcbData
, &version
, sizeof(version
));
489 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
494 static BOOL
CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
495 DWORD cbData
, BOOL fFinal
)
497 CHashEncodeMsg
*msg
= hCryptMsg
;
500 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
502 if (msg
->base
.state
== MsgStateFinalized
)
503 SetLastError(CRYPT_E_MSG_ERROR
);
504 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
506 /* Doesn't do much, as stream output is never called, and you
507 * can't get the content.
509 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
510 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
515 SetLastError(CRYPT_E_MSG_ERROR
);
518 ret
= CryptHashData(msg
->hash
, pbData
, cbData
, 0);
521 msg
->data
.pbData
= CryptMemAlloc(cbData
);
522 if (msg
->data
.pbData
)
524 memcpy(msg
->data
.pbData
+ msg
->data
.cbData
, pbData
, cbData
);
525 msg
->data
.cbData
+= cbData
;
530 msg
->base
.state
= MsgStateFinalized
;
536 static HCRYPTMSG
CHashEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
537 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
540 const CMSG_HASHED_ENCODE_INFO
*info
= pvMsgEncodeInfo
;
544 if (info
->cbSize
!= sizeof(CMSG_HASHED_ENCODE_INFO
))
546 SetLastError(E_INVALIDARG
);
549 if (!(algID
= CertOIDToAlgId(info
->HashAlgorithm
.pszObjId
)))
551 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
554 if (info
->hCryptProv
)
555 prov
= info
->hCryptProv
;
558 prov
= CRYPT_GetDefaultProvider();
559 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
561 msg
= CryptMemAlloc(sizeof(CHashEncodeMsg
));
564 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
565 CHashEncodeMsg_Close
, CHashEncodeMsg_GetParam
, CHashEncodeMsg_Update
,
566 CRYPT_DefaultMsgControl
);
568 msg
->data
.cbData
= 0;
569 msg
->data
.pbData
= NULL
;
570 if (!CryptCreateHash(prov
, algID
, 0, 0, &msg
->hash
))
579 typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
582 PCERT_INFO pCertInfo
;
583 HCRYPTPROV hCryptProv
;
585 CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm
;
588 PCRYPT_ATTRIBUTE rgAuthAttr
;
590 PCRYPT_ATTRIBUTE rgUnauthAttr
;
592 CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm
;
593 void *pvHashEncryptionAuxInfo
;
594 } CMSG_SIGNER_ENCODE_INFO_WITH_CMS
;
596 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
600 CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*rgSigners
;
602 PCERT_BLOB rgCertEncoded
;
604 PCRL_BLOB rgCrlEncoded
;
605 DWORD cAttrCertEncoded
;
606 PCERT_BLOB rgAttrCertEncoded
;
607 } CMSG_SIGNED_ENCODE_INFO_WITH_CMS
;
609 static BOOL
CRYPT_IsValidSigner(const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*signer
)
611 if (signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO
) &&
612 signer
->cbSize
!= sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
614 SetLastError(E_INVALIDARG
);
617 if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
619 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
621 SetLastError(E_INVALIDARG
);
624 if (!signer
->pCertInfo
->Issuer
.cbData
)
626 SetLastError(E_INVALIDARG
);
630 else if (signer
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS
))
632 switch (signer
->SignerId
.dwIdChoice
)
635 if (!signer
->pCertInfo
->SerialNumber
.cbData
)
637 SetLastError(E_INVALIDARG
);
640 if (!signer
->pCertInfo
->Issuer
.cbData
)
642 SetLastError(E_INVALIDARG
);
646 case CERT_ID_ISSUER_SERIAL_NUMBER
:
647 if (!signer
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
)
649 SetLastError(E_INVALIDARG
);
652 if (!signer
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
654 SetLastError(E_INVALIDARG
);
658 case CERT_ID_KEY_IDENTIFIER
:
659 if (!signer
->SignerId
.u
.KeyId
.cbData
)
661 SetLastError(E_INVALIDARG
);
666 SetLastError(E_INVALIDARG
);
668 if (signer
->HashEncryptionAlgorithm
.pszObjId
)
670 FIXME("CMSG_SIGNER_ENCODE_INFO with CMS fields unsupported\n");
674 if (!signer
->hCryptProv
)
676 SetLastError(E_INVALIDARG
);
679 if (!CertOIDToAlgId(signer
->HashAlgorithm
.pszObjId
))
681 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
687 static BOOL
CRYPT_ConstructBlob(CRYPT_DATA_BLOB
*out
, const CRYPT_DATA_BLOB
*in
)
691 out
->cbData
= in
->cbData
;
694 out
->pbData
= CryptMemAlloc(out
->cbData
);
696 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
705 static BOOL
CRYPT_ConstructBlobArray(DWORD
*outCBlobs
,
706 PCRYPT_DATA_BLOB
*outPBlobs
, DWORD cBlobs
, const CRYPT_DATA_BLOB
*pBlobs
)
713 *outPBlobs
= CryptMemAlloc(cBlobs
* sizeof(CRYPT_DATA_BLOB
));
718 memset(*outPBlobs
, 0, cBlobs
* sizeof(CRYPT_DATA_BLOB
));
719 for (i
= 0; ret
&& i
< cBlobs
; i
++)
720 ret
= CRYPT_ConstructBlob(&(*outPBlobs
)[i
], &pBlobs
[i
]);
728 static void CRYPT_FreeBlobArray(DWORD cBlobs
, PCRYPT_DATA_BLOB blobs
)
732 for (i
= 0; i
< cBlobs
; i
++)
733 CryptMemFree(blobs
[i
].pbData
);
737 static BOOL
CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE
*out
,
738 const CRYPT_ATTRIBUTE
*in
)
742 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
745 strcpy(out
->pszObjId
, in
->pszObjId
);
746 ret
= CRYPT_ConstructBlobArray(&out
->cValue
, &out
->rgValue
,
747 in
->cValue
, in
->rgValue
);
754 static BOOL
CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES
*out
,
755 const CRYPT_ATTRIBUTES
*in
)
759 out
->cAttr
= in
->cAttr
;
762 out
->rgAttr
= CryptMemAlloc(out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
767 memset(out
->rgAttr
, 0, out
->cAttr
* sizeof(CRYPT_ATTRIBUTE
));
768 for (i
= 0; ret
&& i
< out
->cAttr
; i
++)
769 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[i
], &in
->rgAttr
[i
]);
779 /* Constructs a CMSG_CMS_SIGNER_INFO from a CMSG_SIGNER_ENCODE_INFO_WITH_CMS. */
780 static BOOL
CSignerInfo_Construct(CMSG_CMS_SIGNER_INFO
*info
,
781 const CMSG_SIGNER_ENCODE_INFO_WITH_CMS
*in
)
785 if (in
->cbSize
== sizeof(CMSG_SIGNER_ENCODE_INFO
))
787 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
788 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
789 &in
->pCertInfo
->Issuer
);
791 ret
= CRYPT_ConstructBlob(
792 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
793 &in
->pCertInfo
->SerialNumber
);
794 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
795 info
->HashEncryptionAlgorithm
.pszObjId
=
796 in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
;
798 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
799 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.Parameters
);
803 const CRYPT_ALGORITHM_IDENTIFIER
*pEncrAlg
;
805 /* Implicitly in->cbSize == sizeof(CMSG_SIGNER_ENCODE_INFO_WITH_CMS).
806 * See CRYPT_IsValidSigner.
808 if (!in
->SignerId
.dwIdChoice
)
810 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
811 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
812 &in
->pCertInfo
->Issuer
);
814 ret
= CRYPT_ConstructBlob(
815 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
816 &in
->pCertInfo
->SerialNumber
);
817 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
819 else if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
821 info
->dwVersion
= CMSG_SIGNER_INFO_V1
;
822 info
->SignerId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
823 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
824 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
);
826 ret
= CRYPT_ConstructBlob(
827 &info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
828 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
);
832 /* Implicitly dwIdChoice == CERT_ID_KEY_IDENTIFIER */
833 info
->dwVersion
= CMSG_SIGNER_INFO_V3
;
834 info
->SignerId
.dwIdChoice
= CERT_ID_KEY_IDENTIFIER
;
835 ret
= CRYPT_ConstructBlob(&info
->SignerId
.u
.KeyId
,
836 &in
->SignerId
.u
.KeyId
);
838 pEncrAlg
= in
->HashEncryptionAlgorithm
.pszObjId
?
839 &in
->HashEncryptionAlgorithm
:
840 &in
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
;
841 info
->HashEncryptionAlgorithm
.pszObjId
= pEncrAlg
->pszObjId
;
843 ret
= CRYPT_ConstructBlob(&info
->HashEncryptionAlgorithm
.Parameters
,
844 &pEncrAlg
->Parameters
);
846 /* Assumption: algorithm IDs will point to static strings, not
847 * stack-based ones, so copying the pointer values is safe.
849 info
->HashAlgorithm
.pszObjId
= in
->HashAlgorithm
.pszObjId
;
851 ret
= CRYPT_ConstructBlob(&info
->HashAlgorithm
.Parameters
,
852 &in
->HashAlgorithm
.Parameters
);
854 ret
= CRYPT_ConstructAttributes(&info
->AuthAttrs
,
855 (CRYPT_ATTRIBUTES
*)&in
->cAuthAttr
);
857 ret
= CRYPT_ConstructAttributes(&info
->UnauthAttrs
,
858 (CRYPT_ATTRIBUTES
*)&in
->cUnauthAttr
);
862 static void CSignerInfo_Free(CMSG_CMS_SIGNER_INFO
*info
)
866 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
868 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
869 CryptMemFree(info
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
872 CryptMemFree(info
->SignerId
.u
.KeyId
.pbData
);
873 CryptMemFree(info
->HashAlgorithm
.Parameters
.pbData
);
874 CryptMemFree(info
->HashEncryptionAlgorithm
.Parameters
.pbData
);
875 CryptMemFree(info
->EncryptedHash
.pbData
);
876 for (i
= 0; i
< info
->AuthAttrs
.cAttr
; i
++)
878 for (j
= 0; j
< info
->AuthAttrs
.rgAttr
[i
].cValue
; j
++)
879 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
880 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].rgValue
);
881 CryptMemFree(info
->AuthAttrs
.rgAttr
[i
].pszObjId
);
883 CryptMemFree(info
->AuthAttrs
.rgAttr
);
884 for (i
= 0; i
< info
->UnauthAttrs
.cAttr
; i
++)
886 for (j
= 0; j
< info
->UnauthAttrs
.rgAttr
[i
].cValue
; j
++)
887 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
[j
].pbData
);
888 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].rgValue
);
889 CryptMemFree(info
->UnauthAttrs
.rgAttr
[i
].pszObjId
);
891 CryptMemFree(info
->UnauthAttrs
.rgAttr
);
894 typedef struct _CSignerHandles
896 HCRYPTHASH contentHash
;
897 HCRYPTHASH authAttrHash
;
900 typedef struct _CSignedMsgData
902 CRYPT_SIGNED_INFO
*info
;
904 CSignerHandles
*signerHandles
;
907 /* Constructs the signer handles for the signerIndex'th signer of msg_data.
908 * Assumes signerIndex is a valid idnex, and that msg_data's info has already
911 static BOOL
CSignedMsgData_ConstructSignerHandles(CSignedMsgData
*msg_data
,
912 DWORD signerIndex
, HCRYPTPROV crypt_prov
)
917 algID
= CertOIDToAlgId(
918 msg_data
->info
->rgSignerInfo
[signerIndex
].HashAlgorithm
.pszObjId
);
919 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
920 &msg_data
->signerHandles
->contentHash
);
921 if (ret
&& msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
> 0)
922 ret
= CryptCreateHash(crypt_prov
, algID
, 0, 0,
923 &msg_data
->signerHandles
->authAttrHash
);
927 /* Allocates a CSignedMsgData's handles. Assumes its info has already been
930 static BOOL
CSignedMsgData_AllocateHandles(CSignedMsgData
*msg_data
)
934 if (msg_data
->info
->cSignerInfo
)
936 msg_data
->signerHandles
=
937 CryptMemAlloc(msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
938 if (msg_data
->signerHandles
)
940 msg_data
->cSignerHandle
= msg_data
->info
->cSignerInfo
;
941 memset(msg_data
->signerHandles
, 0,
942 msg_data
->info
->cSignerInfo
* sizeof(CSignerHandles
));
946 msg_data
->cSignerHandle
= 0;
952 msg_data
->cSignerHandle
= 0;
953 msg_data
->signerHandles
= NULL
;
958 static void CSignedMsgData_CloseHandles(CSignedMsgData
*msg_data
)
962 for (i
= 0; i
< msg_data
->cSignerHandle
; i
++)
964 if (msg_data
->signerHandles
[i
].contentHash
)
965 CryptDestroyHash(msg_data
->signerHandles
[i
].contentHash
);
966 if (msg_data
->signerHandles
[i
].authAttrHash
)
967 CryptDestroyHash(msg_data
->signerHandles
[i
].authAttrHash
);
969 CryptMemFree(msg_data
->signerHandles
);
970 msg_data
->signerHandles
= NULL
;
971 msg_data
->cSignerHandle
= 0;
974 static BOOL
CSignedMsgData_UpdateHash(CSignedMsgData
*msg_data
,
975 const BYTE
*pbData
, DWORD cbData
)
980 for (i
= 0; ret
&& i
< msg_data
->cSignerHandle
; i
++)
981 ret
= CryptHashData(msg_data
->signerHandles
[i
].contentHash
, pbData
,
986 static BOOL
CRYPT_AppendAttribute(CRYPT_ATTRIBUTES
*out
,
987 const CRYPT_ATTRIBUTE
*in
)
991 out
->rgAttr
= CryptMemRealloc(out
->rgAttr
,
992 (out
->cAttr
+ 1) * sizeof(CRYPT_ATTRIBUTE
));
995 ret
= CRYPT_ConstructAttribute(&out
->rgAttr
[out
->cAttr
], in
);
1002 static BOOL
CSignedMsgData_AppendMessageDigestAttribute(
1003 CSignedMsgData
*msg_data
, DWORD signerIndex
)
1007 CRYPT_HASH_BLOB hash
= { 0, NULL
}, encodedHash
= { 0, NULL
};
1008 char messageDigest
[] = szOID_RSA_messageDigest
;
1009 CRYPT_ATTRIBUTE messageDigestAttr
= { messageDigest
, 1, &encodedHash
};
1011 size
= sizeof(DWORD
);
1012 ret
= CryptGetHashParam(
1013 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHSIZE
,
1014 (LPBYTE
)&hash
.cbData
, &size
, 0);
1017 hash
.pbData
= CryptMemAlloc(hash
.cbData
);
1018 ret
= CryptGetHashParam(
1019 msg_data
->signerHandles
[signerIndex
].contentHash
, HP_HASHVAL
,
1020 hash
.pbData
, &hash
.cbData
, 0);
1023 ret
= CRYPT_AsnEncodeOctets(0, NULL
, &hash
, CRYPT_ENCODE_ALLOC_FLAG
,
1024 NULL
, (LPBYTE
)&encodedHash
.pbData
, &encodedHash
.cbData
);
1027 ret
= CRYPT_AppendAttribute(
1028 &msg_data
->info
->rgSignerInfo
[signerIndex
].AuthAttrs
,
1029 &messageDigestAttr
);
1030 LocalFree(encodedHash
.pbData
);
1033 CryptMemFree(hash
.pbData
);
1043 static BOOL
CSignedMsgData_UpdateAuthenticatedAttributes(
1044 CSignedMsgData
*msg_data
, SignOrVerify flag
)
1049 TRACE("(%p)\n", msg_data
);
1051 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1053 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1057 BYTE oid_rsa_data_encoded
[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,
1058 0xf7,0x0d,0x01,0x07,0x01 };
1059 CRYPT_DATA_BLOB content
= { sizeof(oid_rsa_data_encoded
),
1060 oid_rsa_data_encoded
};
1061 char contentType
[] = szOID_RSA_contentType
;
1062 CRYPT_ATTRIBUTE contentTypeAttr
= { contentType
, 1, &content
};
1064 /* FIXME: does this depend on inner OID? */
1065 ret
= CRYPT_AppendAttribute(
1066 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
, &contentTypeAttr
);
1068 ret
= CSignedMsgData_AppendMessageDigestAttribute(msg_data
,
1073 LPBYTE encodedAttrs
;
1076 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, PKCS_ATTRIBUTES
,
1077 &msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
,
1078 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &encodedAttrs
, &size
);
1081 ret
= CryptHashData(
1082 msg_data
->signerHandles
[i
].authAttrHash
, encodedAttrs
,
1084 LocalFree(encodedAttrs
);
1089 TRACE("returning %d\n", ret
);
1093 static void CRYPT_ReverseBytes(CRYPT_HASH_BLOB
*hash
)
1098 for (i
= 0; i
< hash
->cbData
/ 2; i
++)
1100 tmp
= hash
->pbData
[hash
->cbData
- i
- 1];
1101 hash
->pbData
[hash
->cbData
- i
- 1] = hash
->pbData
[i
];
1102 hash
->pbData
[i
] = tmp
;
1106 static BOOL
CSignedMsgData_Sign(CSignedMsgData
*msg_data
)
1111 TRACE("(%p)\n", msg_data
);
1113 for (i
= 0; ret
&& i
< msg_data
->info
->cSignerInfo
; i
++)
1117 if (msg_data
->info
->rgSignerInfo
[i
].AuthAttrs
.cAttr
)
1118 hash
= msg_data
->signerHandles
[i
].authAttrHash
;
1120 hash
= msg_data
->signerHandles
[i
].contentHash
;
1121 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0, NULL
,
1122 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1125 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
=
1127 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1128 if (msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
)
1130 ret
= CryptSignHashW(hash
, AT_SIGNATURE
, NULL
, 0,
1131 msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.pbData
,
1132 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
.cbData
);
1135 &msg_data
->info
->rgSignerInfo
[i
].EncryptedHash
);
1144 static BOOL
CSignedMsgData_Update(CSignedMsgData
*msg_data
,
1145 const BYTE
*pbData
, DWORD cbData
, BOOL fFinal
, SignOrVerify flag
)
1147 BOOL ret
= CSignedMsgData_UpdateHash(msg_data
, pbData
, cbData
);
1151 ret
= CSignedMsgData_UpdateAuthenticatedAttributes(msg_data
, flag
);
1152 if (ret
&& flag
== Sign
)
1153 ret
= CSignedMsgData_Sign(msg_data
);
1158 typedef struct _CSignedEncodeMsg
1162 CRYPT_DATA_BLOB data
;
1163 CSignedMsgData msg_data
;
1166 static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1168 CSignedEncodeMsg
*msg
= hCryptMsg
;
1171 CryptMemFree(msg
->innerOID
);
1172 CryptMemFree(msg
->data
.pbData
);
1173 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCertEncoded
,
1174 msg
->msg_data
.info
->rgCertEncoded
);
1175 CRYPT_FreeBlobArray(msg
->msg_data
.info
->cCrlEncoded
,
1176 msg
->msg_data
.info
->rgCrlEncoded
);
1177 for (i
= 0; i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1178 CSignerInfo_Free(&msg
->msg_data
.info
->rgSignerInfo
[i
]);
1179 CSignedMsgData_CloseHandles(&msg
->msg_data
);
1180 CryptMemFree(msg
->msg_data
.info
->rgSignerInfo
);
1181 CryptMemFree(msg
->msg_data
.info
);
1184 static BOOL
CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1185 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1187 CSignedEncodeMsg
*msg
= hCryptMsg
;
1190 switch (dwParamType
)
1192 case CMSG_CONTENT_PARAM
:
1194 CRYPT_CONTENT_INFO info
;
1196 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1197 &info
.Content
.cbData
);
1200 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1201 if (info
.Content
.pbData
)
1203 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1204 info
.Content
.pbData
, &info
.Content
.cbData
);
1207 char oid_rsa_signed
[] = szOID_RSA_signedData
;
1209 info
.pszObjId
= oid_rsa_signed
;
1210 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1211 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1213 CryptMemFree(info
.Content
.pbData
);
1220 case CMSG_BARE_CONTENT_PARAM
:
1222 CRYPT_SIGNED_INFO info
;
1223 BOOL freeContent
= FALSE
;
1225 info
= *msg
->msg_data
.info
;
1226 if (!msg
->innerOID
|| !strcmp(msg
->innerOID
, szOID_RSA_data
))
1228 char oid_rsa_data
[] = szOID_RSA_data
;
1230 /* Quirk: OID is only encoded messages if an update has happened */
1231 if (msg
->base
.state
!= MsgStateInit
)
1232 info
.content
.pszObjId
= oid_rsa_data
;
1234 info
.content
.pszObjId
= NULL
;
1235 if (msg
->data
.cbData
)
1237 CRYPT_DATA_BLOB blob
= { msg
->data
.cbData
, msg
->data
.pbData
};
1239 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
1240 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
1241 &info
.content
.Content
.pbData
, &info
.content
.Content
.cbData
);
1246 info
.content
.Content
.cbData
= 0;
1247 info
.content
.Content
.pbData
= NULL
;
1253 info
.content
.pszObjId
= msg
->innerOID
;
1254 info
.content
.Content
.cbData
= msg
->data
.cbData
;
1255 info
.content
.Content
.pbData
= msg
->data
.pbData
;
1260 ret
= CRYPT_AsnEncodeCMSSignedInfo(&info
, pvData
, pcbData
);
1262 LocalFree(info
.content
.Content
.pbData
);
1266 case CMSG_COMPUTED_HASH_PARAM
:
1267 if (dwIndex
>= msg
->msg_data
.cSignerHandle
)
1268 SetLastError(CRYPT_E_INVALID_INDEX
);
1270 ret
= CryptGetHashParam(
1271 msg
->msg_data
.signerHandles
[dwIndex
].contentHash
, HP_HASHVAL
,
1272 pvData
, pcbData
, 0);
1274 case CMSG_ENCODED_SIGNER
:
1275 if (dwIndex
>= msg
->msg_data
.info
->cSignerInfo
)
1276 SetLastError(CRYPT_E_INVALID_INDEX
);
1278 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1279 CMS_SIGNER_INFO
, &msg
->msg_data
.info
->rgSignerInfo
[dwIndex
], 0,
1280 NULL
, pvData
, pcbData
);
1282 case CMSG_VERSION_PARAM
:
1283 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->msg_data
.info
->version
,
1284 sizeof(msg
->msg_data
.info
->version
));
1287 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1292 static BOOL
CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1293 DWORD cbData
, BOOL fFinal
)
1295 CSignedEncodeMsg
*msg
= hCryptMsg
;
1298 if (msg
->base
.state
== MsgStateFinalized
)
1299 SetLastError(CRYPT_E_MSG_ERROR
);
1300 else if (msg
->base
.streamed
|| (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
1302 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
, fFinal
,
1304 if (msg
->base
.streamed
)
1305 FIXME("streamed partial stub\n");
1306 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1311 SetLastError(CRYPT_E_MSG_ERROR
);
1316 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1317 if (msg
->data
.pbData
)
1319 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1320 msg
->data
.cbData
= cbData
;
1327 ret
= CSignedMsgData_Update(&msg
->msg_data
, pbData
, cbData
,
1329 msg
->base
.state
= MsgStateFinalized
;
1335 static HCRYPTMSG
CSignedEncodeMsg_Open(DWORD dwFlags
,
1336 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1337 PCMSG_STREAM_INFO pStreamInfo
)
1339 const CMSG_SIGNED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1341 CSignedEncodeMsg
*msg
;
1343 if (info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO
) &&
1344 info
->cbSize
!= sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
))
1346 SetLastError(E_INVALIDARG
);
1349 if (info
->cbSize
== sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS
) &&
1350 info
->cAttrCertEncoded
)
1352 FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n");
1355 for (i
= 0; i
< info
->cSigners
; i
++)
1356 if (!CRYPT_IsValidSigner(&info
->rgSigners
[i
]))
1358 msg
= CryptMemAlloc(sizeof(CSignedEncodeMsg
));
1363 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1364 CSignedEncodeMsg_Close
, CSignedEncodeMsg_GetParam
,
1365 CSignedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1366 if (pszInnerContentObjID
)
1368 msg
->innerOID
= CryptMemAlloc(strlen(pszInnerContentObjID
) + 1);
1370 strcpy(msg
->innerOID
, pszInnerContentObjID
);
1375 msg
->innerOID
= NULL
;
1376 msg
->data
.cbData
= 0;
1377 msg
->data
.pbData
= NULL
;
1379 msg
->msg_data
.info
= CryptMemAlloc(sizeof(CRYPT_SIGNED_INFO
));
1381 msg
->msg_data
.info
= NULL
;
1382 if (msg
->msg_data
.info
)
1384 memset(msg
->msg_data
.info
, 0, sizeof(CRYPT_SIGNED_INFO
));
1385 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V1
;
1393 msg
->msg_data
.info
->rgSignerInfo
=
1394 CryptMemAlloc(info
->cSigners
* sizeof(CMSG_CMS_SIGNER_INFO
));
1395 if (msg
->msg_data
.info
->rgSignerInfo
)
1397 msg
->msg_data
.info
->cSignerInfo
= info
->cSigners
;
1398 memset(msg
->msg_data
.info
->rgSignerInfo
, 0,
1399 msg
->msg_data
.info
->cSignerInfo
*
1400 sizeof(CMSG_CMS_SIGNER_INFO
));
1401 ret
= CSignedMsgData_AllocateHandles(&msg
->msg_data
);
1402 for (i
= 0; ret
&& i
< msg
->msg_data
.info
->cSignerInfo
; i
++)
1404 if (info
->rgSigners
[i
].SignerId
.dwIdChoice
==
1405 CERT_ID_KEY_IDENTIFIER
)
1406 msg
->msg_data
.info
->version
= CMSG_SIGNED_DATA_V3
;
1407 ret
= CSignerInfo_Construct(
1408 &msg
->msg_data
.info
->rgSignerInfo
[i
],
1409 &info
->rgSigners
[i
]);
1412 ret
= CSignedMsgData_ConstructSignerHandles(
1413 &msg
->msg_data
, i
, info
->rgSigners
[i
].hCryptProv
);
1414 if (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1415 CryptReleaseContext(info
->rgSigners
[i
].hCryptProv
,
1425 msg
->msg_data
.info
->cSignerInfo
= 0;
1426 msg
->msg_data
.signerHandles
= NULL
;
1427 msg
->msg_data
.cSignerHandle
= 0;
1431 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCertEncoded
,
1432 &msg
->msg_data
.info
->rgCertEncoded
, info
->cCertEncoded
,
1433 info
->rgCertEncoded
);
1435 ret
= CRYPT_ConstructBlobArray(&msg
->msg_data
.info
->cCrlEncoded
,
1436 &msg
->msg_data
.info
->rgCrlEncoded
, info
->cCrlEncoded
,
1437 info
->rgCrlEncoded
);
1440 CSignedEncodeMsg_Close(msg
);
1448 typedef struct _CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
1451 HCRYPTPROV_LEGACY hCryptProv
;
1452 CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm
;
1453 void *pvEncryptionAuxInfo
;
1455 PCERT_INFO
*rgpRecipientCert
;
1456 PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients
;
1458 PCERT_BLOB rgCertEncoded
;
1460 PCRL_BLOB rgCrlEncoded
;
1461 DWORD cAttrCertEncoded
;
1462 PCERT_BLOB rgAttrCertEncoded
;
1463 DWORD cUnprotectedAttr
;
1464 PCRYPT_ATTRIBUTE rgUnprotectedAttr
;
1465 } CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
;
1467 typedef struct _CEnvelopedEncodeMsg
1470 CRYPT_ALGORITHM_IDENTIFIER algo
;
1473 DWORD cRecipientInfo
;
1474 CMSG_KEY_TRANS_RECIPIENT_INFO
*recipientInfo
;
1475 CRYPT_DATA_BLOB data
;
1476 } CEnvelopedEncodeMsg
;
1478 static BOOL
CRYPT_ConstructAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
1479 const CRYPT_ALGORITHM_IDENTIFIER
*in
)
1481 out
->pszObjId
= CryptMemAlloc(strlen(in
->pszObjId
) + 1);
1484 strcpy(out
->pszObjId
, in
->pszObjId
);
1485 return CRYPT_ConstructBlob(&out
->Parameters
, &in
->Parameters
);
1491 static BOOL
CRYPT_ConstructBitBlob(CRYPT_BIT_BLOB
*out
, const CRYPT_BIT_BLOB
*in
)
1493 out
->cbData
= in
->cbData
;
1494 out
->cUnusedBits
= in
->cUnusedBits
;
1497 out
->pbData
= CryptMemAlloc(out
->cbData
);
1499 memcpy(out
->pbData
, in
->pbData
, out
->cbData
);
1508 static BOOL
CRYPT_GenKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, ALG_ID algID
)
1510 static HCRYPTOIDFUNCSET set
= NULL
;
1511 PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY genKeyFunc
= NULL
;
1512 HCRYPTOIDFUNCADDR hFunc
;
1516 set
= CryptInitOIDFunctionSet(CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC
, 0);
1517 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1518 info
->ContentEncryptionAlgorithm
.pszObjId
, 0, (void **)&genKeyFunc
, &hFunc
);
1521 ret
= genKeyFunc(info
, 0, NULL
);
1522 CryptFreeOIDFunctionAddress(hFunc
, 0);
1525 ret
= CryptGenKey(info
->hCryptProv
, algID
, CRYPT_EXPORTABLE
,
1526 &info
->hContentEncryptKey
);
1530 static BOOL WINAPI
CRYPT_ExportKeyTrans(
1531 PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo
,
1532 PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo
,
1533 PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo
,
1534 DWORD dwFlags
, void *pvReserved
)
1536 CERT_PUBLIC_KEY_INFO keyInfo
;
1540 ret
= CRYPT_ConstructAlgorithmId(&keyInfo
.Algorithm
,
1541 &pKeyTransEncodeInfo
->KeyEncryptionAlgorithm
);
1543 CRYPT_ConstructBitBlob(&keyInfo
.PublicKey
,
1544 &pKeyTransEncodeInfo
->RecipientPublicKey
);
1547 ret
= CryptImportPublicKeyInfo(pKeyTransEncodeInfo
->hCryptProv
,
1548 X509_ASN_ENCODING
, &keyInfo
, &expKey
);
1553 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
, expKey
,
1554 SIMPLEBLOB
, 0, NULL
, &size
);
1559 keyBlob
= CryptMemAlloc(size
);
1562 ret
= CryptExportKey(pContentEncryptInfo
->hContentEncryptKey
,
1563 expKey
, SIMPLEBLOB
, 0, keyBlob
, &size
);
1566 DWORD head
= sizeof(BLOBHEADER
) + sizeof(ALG_ID
);
1568 pKeyTransEncryptInfo
->EncryptedKey
.pbData
=
1569 CryptMemAlloc(size
- head
);
1570 if (pKeyTransEncryptInfo
->EncryptedKey
.pbData
)
1574 pKeyTransEncryptInfo
->EncryptedKey
.cbData
= size
- head
;
1575 for (i
= size
- 1; i
>= head
; --i
, ++k
)
1576 pKeyTransEncryptInfo
->EncryptedKey
.pbData
[k
] =
1582 CryptMemFree(keyBlob
);
1587 CryptDestroyKey(expKey
);
1590 CryptMemFree(keyInfo
.PublicKey
.pbData
);
1591 CryptMemFree(keyInfo
.Algorithm
.pszObjId
);
1592 CryptMemFree(keyInfo
.Algorithm
.Parameters
.pbData
);
1596 static BOOL
CRYPT_ExportEncryptedKey(CMSG_CONTENT_ENCRYPT_INFO
*info
, DWORD i
,
1597 CRYPT_DATA_BLOB
*key
)
1599 static HCRYPTOIDFUNCSET set
= NULL
;
1600 PFN_CMSG_EXPORT_KEY_TRANS exportKeyFunc
= NULL
;
1601 HCRYPTOIDFUNCADDR hFunc
= NULL
;
1602 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1603 info
->rgCmsRecipients
[i
].u
.pKeyTrans
;
1604 CMSG_KEY_TRANS_ENCRYPT_INFO encryptInfo
;
1607 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
1608 encryptInfo
.cbSize
= sizeof(encryptInfo
);
1609 encryptInfo
.dwRecipientIndex
= i
;
1610 ret
= CRYPT_ConstructAlgorithmId(&encryptInfo
.KeyEncryptionAlgorithm
,
1611 &encodeInfo
->KeyEncryptionAlgorithm
);
1614 set
= CryptInitOIDFunctionSet(CMSG_OID_EXPORT_KEY_TRANS_FUNC
, 0);
1615 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
,
1616 encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
, 0, (void **)&exportKeyFunc
,
1619 exportKeyFunc
= CRYPT_ExportKeyTrans
;
1622 ret
= exportKeyFunc(info
, encodeInfo
, &encryptInfo
, 0, NULL
);
1625 key
->cbData
= encryptInfo
.EncryptedKey
.cbData
;
1626 key
->pbData
= encryptInfo
.EncryptedKey
.pbData
;
1630 CryptFreeOIDFunctionAddress(hFunc
, 0);
1632 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.pszObjId
);
1633 CryptMemFree(encryptInfo
.KeyEncryptionAlgorithm
.Parameters
.pbData
);
1637 static LPVOID WINAPI
mem_alloc(size_t size
)
1639 return HeapAlloc(GetProcessHeap(), 0, size
);
1642 static VOID WINAPI
mem_free(LPVOID pv
)
1644 HeapFree(GetProcessHeap(), 0, pv
);
1648 static BOOL
CContentEncryptInfo_Construct(CMSG_CONTENT_ENCRYPT_INFO
*info
,
1649 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*in
, HCRYPTPROV prov
)
1653 info
->cbSize
= sizeof(CMSG_CONTENT_ENCRYPT_INFO
);
1654 info
->hCryptProv
= prov
;
1655 ret
= CRYPT_ConstructAlgorithmId(&info
->ContentEncryptionAlgorithm
,
1656 &in
->ContentEncryptionAlgorithm
);
1657 info
->pvEncryptionAuxInfo
= in
->pvEncryptionAuxInfo
;
1658 info
->cRecipients
= in
->cRecipients
;
1661 info
->rgCmsRecipients
= CryptMemAlloc(in
->cRecipients
*
1662 sizeof(CMSG_RECIPIENT_ENCODE_INFO
));
1663 if (info
->rgCmsRecipients
)
1667 for (i
= 0; ret
&& i
< in
->cRecipients
; ++i
)
1669 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
;
1670 CERT_INFO
*cert
= in
->rgpRecipientCert
[i
];
1672 info
->rgCmsRecipients
[i
].dwRecipientChoice
=
1673 CMSG_KEY_TRANS_RECIPIENT
;
1674 encodeInfo
= CryptMemAlloc(sizeof(*encodeInfo
));
1675 info
->rgCmsRecipients
[i
].u
.pKeyTrans
= encodeInfo
;
1678 encodeInfo
->cbSize
= sizeof(*encodeInfo
);
1679 ret
= CRYPT_ConstructAlgorithmId(
1680 &encodeInfo
->KeyEncryptionAlgorithm
,
1681 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1682 encodeInfo
->pvKeyEncryptionAuxInfo
= NULL
;
1683 encodeInfo
->hCryptProv
= prov
;
1685 ret
= CRYPT_ConstructBitBlob(
1686 &encodeInfo
->RecipientPublicKey
,
1687 &cert
->SubjectPublicKeyInfo
.PublicKey
);
1689 ret
= CRYPT_ConstructBlob(
1690 &encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.Issuer
,
1693 ret
= CRYPT_ConstructBlob(
1694 &encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
,
1695 &cert
->SerialNumber
);
1704 info
->pfnAlloc
= mem_alloc
;
1705 info
->pfnFree
= mem_free
;
1709 static void CContentEncryptInfo_Free(CMSG_CONTENT_ENCRYPT_INFO
*info
)
1711 CryptMemFree(info
->ContentEncryptionAlgorithm
.pszObjId
);
1712 CryptMemFree(info
->ContentEncryptionAlgorithm
.Parameters
.pbData
);
1713 if (info
->rgCmsRecipients
)
1717 for (i
= 0; i
< info
->cRecipients
; ++i
)
1719 CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO
*encodeInfo
=
1720 info
->rgCmsRecipients
[i
].u
.pKeyTrans
;
1722 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.pszObjId
);
1723 CryptMemFree(encodeInfo
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1724 CryptMemFree(encodeInfo
->RecipientPublicKey
.pbData
);
1726 encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
1728 encodeInfo
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
1729 CryptMemFree(encodeInfo
);
1731 CryptMemFree(info
->rgCmsRecipients
);
1735 static BOOL
CRecipientInfo_Construct(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
,
1736 const CERT_INFO
*cert
, CRYPT_DATA_BLOB
*key
)
1740 info
->dwVersion
= CMSG_KEY_TRANS_PKCS_1_5_VERSION
;
1741 info
->RecipientId
.dwIdChoice
= CERT_ID_ISSUER_SERIAL_NUMBER
;
1742 ret
= CRYPT_ConstructBlob(&info
->RecipientId
.u
.IssuerSerialNumber
.Issuer
,
1745 ret
= CRYPT_ConstructBlob(
1746 &info
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
,
1747 &cert
->SerialNumber
);
1749 ret
= CRYPT_ConstructAlgorithmId(&info
->KeyEncryptionAlgorithm
,
1750 &cert
->SubjectPublicKeyInfo
.Algorithm
);
1751 info
->EncryptedKey
.cbData
= key
->cbData
;
1752 info
->EncryptedKey
.pbData
= key
->pbData
;
1756 static void CRecipientInfo_Free(CMSG_KEY_TRANS_RECIPIENT_INFO
*info
)
1758 CryptMemFree(info
->RecipientId
.u
.IssuerSerialNumber
.Issuer
.pbData
);
1759 CryptMemFree(info
->RecipientId
.u
.IssuerSerialNumber
.SerialNumber
.pbData
);
1760 CryptMemFree(info
->KeyEncryptionAlgorithm
.pszObjId
);
1761 CryptMemFree(info
->KeyEncryptionAlgorithm
.Parameters
.pbData
);
1762 CryptMemFree(info
->EncryptedKey
.pbData
);
1765 static void CEnvelopedEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
1767 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1769 CryptMemFree(msg
->algo
.pszObjId
);
1770 CryptMemFree(msg
->algo
.Parameters
.pbData
);
1771 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
1772 CryptReleaseContext(msg
->prov
, 0);
1773 CryptDestroyKey(msg
->key
);
1774 if (msg
->recipientInfo
)
1778 for (i
= 0; i
< msg
->cRecipientInfo
; ++i
)
1779 CRecipientInfo_Free(&msg
->recipientInfo
[i
]);
1780 CryptMemFree(msg
->recipientInfo
);
1782 CryptMemFree(msg
->data
.pbData
);
1785 static BOOL
CEnvelopedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
1786 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
1788 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1791 switch (dwParamType
)
1793 case CMSG_BARE_CONTENT_PARAM
:
1794 if (msg
->base
.streamed
)
1795 SetLastError(E_INVALIDARG
);
1798 char oid_rsa_data
[] = szOID_RSA_data
;
1799 CRYPT_ENVELOPED_DATA envelopedData
= {
1800 CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION
, msg
->cRecipientInfo
,
1801 msg
->recipientInfo
, { oid_rsa_data
, {
1803 { msg
->algo
.Parameters
.cbData
, msg
->algo
.Parameters
.pbData
}
1805 { msg
->data
.cbData
, msg
->data
.pbData
}
1809 ret
= CRYPT_AsnEncodePKCSEnvelopedData(&envelopedData
, pvData
,
1813 case CMSG_CONTENT_PARAM
:
1815 CRYPT_CONTENT_INFO info
;
1817 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
,
1818 &info
.Content
.cbData
);
1821 info
.Content
.pbData
= CryptMemAlloc(info
.Content
.cbData
);
1822 if (info
.Content
.pbData
)
1824 ret
= CryptMsgGetParam(hCryptMsg
, CMSG_BARE_CONTENT_PARAM
, 0,
1825 info
.Content
.pbData
, &info
.Content
.cbData
);
1828 char oid_rsa_enveloped
[] = szOID_RSA_envelopedData
;
1830 info
.pszObjId
= oid_rsa_enveloped
;
1831 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
,
1832 PKCS_CONTENT_INFO
, &info
, 0, NULL
, pvData
, pcbData
);
1834 CryptMemFree(info
.Content
.pbData
);
1842 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
1847 static BOOL
CEnvelopedEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
1848 DWORD cbData
, BOOL fFinal
)
1850 CEnvelopedEncodeMsg
*msg
= hCryptMsg
;
1853 if (msg
->base
.state
== MsgStateFinalized
)
1854 SetLastError(CRYPT_E_MSG_ERROR
);
1855 else if (msg
->base
.streamed
)
1857 FIXME("streamed stub\n");
1858 msg
->base
.state
= fFinal
? MsgStateFinalized
: MsgStateUpdated
;
1865 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
1866 SetLastError(E_INVALIDARG
);
1868 SetLastError(CRYPT_E_MSG_ERROR
);
1874 DWORD dataLen
= cbData
;
1876 msg
->data
.cbData
= cbData
;
1877 msg
->data
.pbData
= CryptMemAlloc(cbData
);
1878 if (msg
->data
.pbData
)
1880 memcpy(msg
->data
.pbData
, pbData
, cbData
);
1881 ret
= CryptEncrypt(msg
->key
, 0, TRUE
, 0, msg
->data
.pbData
,
1882 &dataLen
, msg
->data
.cbData
);
1883 msg
->data
.cbData
= dataLen
;
1884 if (dataLen
> cbData
)
1886 msg
->data
.pbData
= CryptMemRealloc(msg
->data
.pbData
,
1888 if (msg
->data
.pbData
)
1891 ret
= CryptEncrypt(msg
->key
, 0, TRUE
, 0,
1892 msg
->data
.pbData
, &dataLen
, msg
->data
.cbData
);
1898 CryptMemFree(msg
->data
.pbData
);
1904 msg
->data
.cbData
= 0;
1905 msg
->data
.pbData
= NULL
;
1910 msg
->base
.state
= MsgStateFinalized
;
1916 static HCRYPTMSG
CEnvelopedEncodeMsg_Open(DWORD dwFlags
,
1917 const void *pvMsgEncodeInfo
, LPCSTR pszInnerContentObjID
,
1918 PCMSG_STREAM_INFO pStreamInfo
)
1920 CEnvelopedEncodeMsg
*msg
;
1921 const CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
*info
= pvMsgEncodeInfo
;
1925 if (info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO
) &&
1926 info
->cbSize
!= sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1928 SetLastError(E_INVALIDARG
);
1931 if (info
->cbSize
== sizeof(CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
))
1932 FIXME("CMS fields unsupported\n");
1933 if (!(algID
= CertOIDToAlgId(info
->ContentEncryptionAlgorithm
.pszObjId
)))
1935 SetLastError(CRYPT_E_UNKNOWN_ALGO
);
1938 if (info
->cRecipients
&& !info
->rgpRecipientCert
)
1940 SetLastError(E_INVALIDARG
);
1943 if (info
->hCryptProv
)
1944 prov
= info
->hCryptProv
;
1947 prov
= CRYPT_GetDefaultProvider();
1948 dwFlags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
1950 msg
= CryptMemAlloc(sizeof(CEnvelopedEncodeMsg
));
1953 CRYPT_DATA_BLOB encryptedKey
= { 0, NULL
};
1954 CMSG_CONTENT_ENCRYPT_INFO encryptInfo
;
1958 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
1959 CEnvelopedEncodeMsg_Close
, CEnvelopedEncodeMsg_GetParam
,
1960 CEnvelopedEncodeMsg_Update
, CRYPT_DefaultMsgControl
);
1961 ret
= CRYPT_ConstructAlgorithmId(&msg
->algo
,
1962 &info
->ContentEncryptionAlgorithm
);
1964 msg
->data
.cbData
= 0;
1965 msg
->data
.pbData
= NULL
;
1966 msg
->cRecipientInfo
= info
->cRecipients
;
1967 msg
->recipientInfo
= CryptMemAlloc(info
->cRecipients
*
1968 sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
));
1969 if (!msg
->recipientInfo
)
1971 memset(&encryptInfo
, 0, sizeof(encryptInfo
));
1974 ret
= CContentEncryptInfo_Construct(&encryptInfo
, info
, prov
);
1977 ret
= CRYPT_GenKey(&encryptInfo
, algID
);
1979 msg
->key
= encryptInfo
.hContentEncryptKey
;
1982 for (i
= 0; ret
&& i
< msg
->cRecipientInfo
; ++i
)
1984 ret
= CRYPT_ExportEncryptedKey(&encryptInfo
, i
, &encryptedKey
);
1986 ret
= CRecipientInfo_Construct(&msg
->recipientInfo
[i
],
1987 info
->rgpRecipientCert
[i
], &encryptedKey
);
1989 CContentEncryptInfo_Free(&encryptInfo
);
1996 if (!msg
&& (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
))
1997 CryptReleaseContext(prov
, 0);
2001 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
2002 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
2003 PCMSG_STREAM_INFO pStreamInfo
)
2005 HCRYPTMSG msg
= NULL
;
2007 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
2008 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
2010 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
2012 SetLastError(E_INVALIDARG
);
2018 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2019 pszInnerContentObjID
, pStreamInfo
);
2022 msg
= CHashEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2023 pszInnerContentObjID
, pStreamInfo
);
2026 msg
= CSignedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2027 pszInnerContentObjID
, pStreamInfo
);
2029 case CMSG_ENVELOPED
:
2030 msg
= CEnvelopedEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
2031 pszInnerContentObjID
, pStreamInfo
);
2033 case CMSG_SIGNED_AND_ENVELOPED
:
2034 case CMSG_ENCRYPTED
:
2035 /* defined but invalid, fall through */
2037 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2042 typedef struct _CEnvelopedDecodeMsg
2044 CRYPT_ENVELOPED_DATA
*data
;
2045 HCRYPTPROV crypt_prov
;
2046 CRYPT_DATA_BLOB content
;
2048 } CEnvelopedDecodeMsg
;
2050 typedef struct _CDecodeMsg
2054 HCRYPTPROV crypt_prov
;
2057 CSignedMsgData signed_data
;
2058 CEnvelopedDecodeMsg enveloped_data
;
2060 CRYPT_DATA_BLOB msg_data
;
2061 CRYPT_DATA_BLOB detached_data
;
2062 CONTEXT_PROPERTY_LIST
*properties
;
2065 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg
)
2067 CDecodeMsg
*msg
= hCryptMsg
;
2069 if (msg
->base
.open_flags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
)
2070 CryptReleaseContext(msg
->crypt_prov
, 0);
2075 CryptDestroyHash(msg
->u
.hash
);
2077 case CMSG_ENVELOPED
:
2078 if (msg
->u
.enveloped_data
.crypt_prov
)
2079 CryptReleaseContext(msg
->u
.enveloped_data
.crypt_prov
, 0);
2080 LocalFree(msg
->u
.enveloped_data
.data
);
2081 CryptMemFree(msg
->u
.enveloped_data
.content
.pbData
);
2084 if (msg
->u
.signed_data
.info
)
2086 LocalFree(msg
->u
.signed_data
.info
);
2087 CSignedMsgData_CloseHandles(&msg
->u
.signed_data
);
2091 CryptMemFree(msg
->msg_data
.pbData
);
2092 CryptMemFree(msg
->detached_data
.pbData
);
2093 ContextPropertyList_Free(msg
->properties
);
2096 static BOOL
CDecodeMsg_CopyData(CRYPT_DATA_BLOB
*blob
, const BYTE
*pbData
,
2104 blob
->pbData
= CryptMemRealloc(blob
->pbData
,
2105 blob
->cbData
+ cbData
);
2107 blob
->pbData
= CryptMemAlloc(cbData
);
2110 memcpy(blob
->pbData
+ blob
->cbData
, pbData
, cbData
);
2111 blob
->cbData
+= cbData
;
2119 static BOOL
CDecodeMsg_DecodeDataContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
)
2122 CRYPT_DATA_BLOB
*data
;
2125 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
2126 blob
->pbData
, blob
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &data
, &size
);
2129 ret
= ContextPropertyList_SetProperty(msg
->properties
,
2130 CMSG_CONTENT_PARAM
, data
->pbData
, data
->cbData
);
2136 static void CDecodeMsg_SaveAlgorithmID(CDecodeMsg
*msg
, DWORD param
,
2137 const CRYPT_ALGORITHM_IDENTIFIER
*id
)
2139 static const BYTE nullParams
[] = { ASN_NULL
, 0 };
2140 CRYPT_ALGORITHM_IDENTIFIER
*copy
;
2141 DWORD len
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
2143 /* Linearize algorithm id */
2144 len
+= strlen(id
->pszObjId
) + 1;
2145 len
+= id
->Parameters
.cbData
;
2146 copy
= CryptMemAlloc(len
);
2150 (LPSTR
)((BYTE
*)copy
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2151 strcpy(copy
->pszObjId
, id
->pszObjId
);
2152 copy
->Parameters
.pbData
= (BYTE
*)copy
->pszObjId
+ strlen(id
->pszObjId
)
2154 /* Trick: omit NULL parameters */
2155 if (id
->Parameters
.cbData
== sizeof(nullParams
) &&
2156 !memcmp(id
->Parameters
.pbData
, nullParams
, sizeof(nullParams
)))
2158 copy
->Parameters
.cbData
= 0;
2159 len
-= sizeof(nullParams
);
2162 copy
->Parameters
.cbData
= id
->Parameters
.cbData
;
2163 if (copy
->Parameters
.cbData
)
2164 memcpy(copy
->Parameters
.pbData
, id
->Parameters
.pbData
,
2165 id
->Parameters
.cbData
);
2166 ContextPropertyList_SetProperty(msg
->properties
, param
, (BYTE
*)copy
,
2172 static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER
*id
)
2174 id
->pszObjId
= (LPSTR
)((BYTE
*)id
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER
));
2175 id
->Parameters
.pbData
= (BYTE
*)id
->pszObjId
+ strlen(id
->pszObjId
) + 1;
2178 static BOOL
CDecodeMsg_DecodeHashedContent(CDecodeMsg
*msg
,
2179 const CRYPT_DER_BLOB
*blob
)
2182 CRYPT_DIGESTED_DATA
*digestedData
;
2185 ret
= CRYPT_AsnDecodePKCSDigestedData(blob
->pbData
, blob
->cbData
,
2186 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_DIGESTED_DATA
*)&digestedData
,
2190 ContextPropertyList_SetProperty(msg
->properties
, CMSG_VERSION_PARAM
,
2191 (const BYTE
*)&digestedData
->version
, sizeof(digestedData
->version
));
2192 CDecodeMsg_SaveAlgorithmID(msg
, CMSG_HASH_ALGORITHM_PARAM
,
2193 &digestedData
->DigestAlgorithm
);
2194 ContextPropertyList_SetProperty(msg
->properties
,
2195 CMSG_INNER_CONTENT_TYPE_PARAM
,
2196 (const BYTE
*)digestedData
->ContentInfo
.pszObjId
,
2197 digestedData
->ContentInfo
.pszObjId
?
2198 strlen(digestedData
->ContentInfo
.pszObjId
) + 1 : 0);
2199 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
))
2201 if (digestedData
->ContentInfo
.Content
.cbData
)
2202 CDecodeMsg_DecodeDataContent(msg
,
2203 &digestedData
->ContentInfo
.Content
);
2205 ContextPropertyList_SetProperty(msg
->properties
,
2206 CMSG_CONTENT_PARAM
, NULL
, 0);
2208 ContextPropertyList_SetProperty(msg
->properties
, CMSG_HASH_DATA_PARAM
,
2209 digestedData
->hash
.pbData
, digestedData
->hash
.cbData
);
2210 LocalFree(digestedData
);
2215 static BOOL
CDecodeMsg_DecodeEnvelopedContent(CDecodeMsg
*msg
,
2216 const CRYPT_DER_BLOB
*blob
)
2219 CRYPT_ENVELOPED_DATA
*envelopedData
;
2222 ret
= CRYPT_AsnDecodePKCSEnvelopedData(blob
->pbData
, blob
->cbData
,
2223 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_ENVELOPED_DATA
*)&envelopedData
,
2226 msg
->u
.enveloped_data
.data
= envelopedData
;
2230 static BOOL
CDecodeMsg_DecodeSignedContent(CDecodeMsg
*msg
,
2231 const CRYPT_DER_BLOB
*blob
)
2234 CRYPT_SIGNED_INFO
*signedInfo
;
2237 ret
= CRYPT_AsnDecodeCMSSignedInfo(blob
->pbData
, blob
->cbData
,
2238 CRYPT_DECODE_ALLOC_FLAG
, NULL
, (CRYPT_SIGNED_INFO
*)&signedInfo
,
2241 msg
->u
.signed_data
.info
= signedInfo
;
2245 /* Decodes the content in blob as the type given, and updates the value
2246 * (type, parameters, etc.) of msg based on what blob contains.
2247 * It doesn't just use msg's type, to allow a recursive call from an implicitly
2248 * typed message once the outer content info has been decoded.
2250 static BOOL
CDecodeMsg_DecodeContent(CDecodeMsg
*msg
, const CRYPT_DER_BLOB
*blob
,
2258 if ((ret
= CDecodeMsg_DecodeDataContent(msg
, blob
)))
2259 msg
->type
= CMSG_DATA
;
2262 if ((ret
= CDecodeMsg_DecodeHashedContent(msg
, blob
)))
2263 msg
->type
= CMSG_HASHED
;
2265 case CMSG_ENVELOPED
:
2266 if ((ret
= CDecodeMsg_DecodeEnvelopedContent(msg
, blob
)))
2267 msg
->type
= CMSG_ENVELOPED
;
2270 if ((ret
= CDecodeMsg_DecodeSignedContent(msg
, blob
)))
2271 msg
->type
= CMSG_SIGNED
;
2275 CRYPT_CONTENT_INFO
*info
;
2278 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
,
2279 msg
->msg_data
.pbData
, msg
->msg_data
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
2280 NULL
, &info
, &size
);
2283 if (!strcmp(info
->pszObjId
, szOID_RSA_data
))
2284 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
, CMSG_DATA
);
2285 else if (!strcmp(info
->pszObjId
, szOID_RSA_digestedData
))
2286 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2288 else if (!strcmp(info
->pszObjId
, szOID_RSA_envelopedData
))
2289 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2291 else if (!strcmp(info
->pszObjId
, szOID_RSA_signedData
))
2292 ret
= CDecodeMsg_DecodeContent(msg
, &info
->Content
,
2296 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2306 static BOOL
CDecodeMsg_FinalizeHashedContent(CDecodeMsg
*msg
,
2307 CRYPT_DER_BLOB
*blob
)
2309 CRYPT_ALGORITHM_IDENTIFIER
*hashAlgoID
= NULL
;
2314 CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, NULL
, &size
);
2315 hashAlgoID
= CryptMemAlloc(size
);
2316 ret
= CryptMsgGetParam(msg
, CMSG_HASH_ALGORITHM_PARAM
, 0, hashAlgoID
,
2319 algID
= CertOIDToAlgId(hashAlgoID
->pszObjId
);
2320 ret
= CryptCreateHash(msg
->crypt_prov
, algID
, 0, 0, &msg
->u
.hash
);
2323 CRYPT_DATA_BLOB content
;
2325 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2327 /* Unlike for non-detached messages, the data were never stored as
2328 * the content param, but were saved in msg->detached_data instead.
2330 content
.pbData
= msg
->detached_data
.pbData
;
2331 content
.cbData
= msg
->detached_data
.cbData
;
2334 ret
= ContextPropertyList_FindProperty(msg
->properties
,
2335 CMSG_CONTENT_PARAM
, &content
);
2337 ret
= CryptHashData(msg
->u
.hash
, content
.pbData
, content
.cbData
, 0);
2339 CryptMemFree(hashAlgoID
);
2343 static BOOL
CDecodeMsg_FinalizeEnvelopedContent(CDecodeMsg
*msg
,
2344 CRYPT_DER_BLOB
*blob
)
2346 CRYPT_DATA_BLOB
*content
;
2348 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2349 content
= &msg
->detached_data
;
2352 &msg
->u
.enveloped_data
.data
->encryptedContentInfo
.encryptedContent
;
2354 return CRYPT_ConstructBlob(&msg
->u
.enveloped_data
.content
, content
);
2357 static BOOL
CDecodeMsg_FinalizeSignedContent(CDecodeMsg
*msg
,
2358 CRYPT_DER_BLOB
*blob
)
2363 ret
= CSignedMsgData_AllocateHandles(&msg
->u
.signed_data
);
2364 for (i
= 0; ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
2365 ret
= CSignedMsgData_ConstructSignerHandles(&msg
->u
.signed_data
, i
,
2369 CRYPT_DATA_BLOB
*content
;
2371 /* Now that we have all the content, update the hash handles with
2372 * it. If the message is a detached message, the content is stored
2373 * in msg->detached_data rather than in the signed message's
2376 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2377 content
= &msg
->detached_data
;
2379 content
= &msg
->u
.signed_data
.info
->content
.Content
;
2380 if (content
->cbData
)
2382 /* If the message is not detached, have to decode the message's
2383 * content if the type is szOID_RSA_data.
2385 if (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) &&
2386 !strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2389 CRYPT_DATA_BLOB
*rsa_blob
;
2391 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
,
2392 X509_OCTET_STRING
, content
->pbData
, content
->cbData
,
2393 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &rsa_blob
, &size
);
2396 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2397 rsa_blob
->pbData
, rsa_blob
->cbData
, TRUE
, Verify
);
2398 LocalFree(rsa_blob
);
2402 ret
= CSignedMsgData_Update(&msg
->u
.signed_data
,
2403 content
->pbData
, content
->cbData
, TRUE
, Verify
);
2409 static BOOL
CDecodeMsg_FinalizeContent(CDecodeMsg
*msg
, CRYPT_DER_BLOB
*blob
)
2416 ret
= CDecodeMsg_FinalizeHashedContent(msg
, blob
);
2418 case CMSG_ENVELOPED
:
2419 ret
= CDecodeMsg_FinalizeEnvelopedContent(msg
, blob
);
2422 ret
= CDecodeMsg_FinalizeSignedContent(msg
, blob
);
2430 static BOOL
CDecodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
2431 DWORD cbData
, BOOL fFinal
)
2433 CDecodeMsg
*msg
= hCryptMsg
;
2436 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
2438 if (msg
->base
.state
== MsgStateFinalized
)
2439 SetLastError(CRYPT_E_MSG_ERROR
);
2440 else if (msg
->base
.streamed
)
2442 FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg
, pbData
,
2444 switch (msg
->base
.state
)
2447 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2450 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2451 msg
->base
.state
= MsgStateDataFinalized
;
2453 msg
->base
.state
= MsgStateFinalized
;
2456 msg
->base
.state
= MsgStateUpdated
;
2458 case MsgStateUpdated
:
2459 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2462 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2463 msg
->base
.state
= MsgStateDataFinalized
;
2465 msg
->base
.state
= MsgStateFinalized
;
2468 case MsgStateDataFinalized
:
2469 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2471 msg
->base
.state
= MsgStateFinalized
;
2474 SetLastError(CRYPT_E_MSG_ERROR
);
2481 SetLastError(CRYPT_E_MSG_ERROR
);
2484 switch (msg
->base
.state
)
2487 ret
= CDecodeMsg_CopyData(&msg
->msg_data
, pbData
, cbData
);
2488 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
2489 msg
->base
.state
= MsgStateDataFinalized
;
2491 msg
->base
.state
= MsgStateFinalized
;
2493 case MsgStateDataFinalized
:
2494 ret
= CDecodeMsg_CopyData(&msg
->detached_data
, pbData
, cbData
);
2495 msg
->base
.state
= MsgStateFinalized
;
2498 SetLastError(CRYPT_E_MSG_ERROR
);
2502 if (ret
&& fFinal
&&
2503 ((msg
->base
.open_flags
& CMSG_DETACHED_FLAG
&& msg
->base
.state
==
2504 MsgStateDataFinalized
) ||
2505 (!(msg
->base
.open_flags
& CMSG_DETACHED_FLAG
) && msg
->base
.state
==
2506 MsgStateFinalized
)))
2507 ret
= CDecodeMsg_DecodeContent(msg
, &msg
->msg_data
, msg
->type
);
2508 if (ret
&& msg
->base
.state
== MsgStateFinalized
)
2509 ret
= CDecodeMsg_FinalizeContent(msg
, &msg
->msg_data
);
2513 static BOOL
CDecodeHashMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2514 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2518 switch (dwParamType
)
2520 case CMSG_TYPE_PARAM
:
2521 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2523 case CMSG_HASH_ALGORITHM_PARAM
:
2525 CRYPT_DATA_BLOB blob
;
2527 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2531 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2533 CRYPT_FixUpAlgorithmID(pvData
);
2536 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2539 case CMSG_COMPUTED_HASH_PARAM
:
2540 ret
= CryptGetHashParam(msg
->u
.hash
, HP_HASHVAL
, pvData
, pcbData
, 0);
2544 CRYPT_DATA_BLOB blob
;
2546 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
2549 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
, blob
.cbData
);
2551 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2557 /* nextData is an in/out parameter - on input it's the memory location in
2558 * which a copy of in's data should be made, and on output it's the memory
2559 * location immediately after out's copy of in's data.
2561 static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB
*out
,
2562 const CRYPT_DATA_BLOB
*in
, LPBYTE
*nextData
)
2564 out
->cbData
= in
->cbData
;
2567 out
->pbData
= *nextData
;
2568 memcpy(out
->pbData
, in
->pbData
, in
->cbData
);
2569 *nextData
+= in
->cbData
;
2573 static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER
*out
,
2574 const CRYPT_ALGORITHM_IDENTIFIER
*in
, LPBYTE
*nextData
)
2578 out
->pszObjId
= (LPSTR
)*nextData
;
2579 strcpy(out
->pszObjId
, in
->pszObjId
);
2580 *nextData
+= strlen(out
->pszObjId
) + 1;
2582 CRYPT_CopyBlob(&out
->Parameters
, &in
->Parameters
, nextData
);
2585 static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES
*out
,
2586 const CRYPT_ATTRIBUTES
*in
, LPBYTE
*nextData
)
2588 out
->cAttr
= in
->cAttr
;
2593 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2594 out
->rgAttr
= (CRYPT_ATTRIBUTE
*)*nextData
;
2595 *nextData
+= in
->cAttr
* sizeof(CRYPT_ATTRIBUTE
);
2596 for (i
= 0; i
< in
->cAttr
; i
++)
2598 if (in
->rgAttr
[i
].pszObjId
)
2600 out
->rgAttr
[i
].pszObjId
= (LPSTR
)*nextData
;
2601 strcpy(out
->rgAttr
[i
].pszObjId
, in
->rgAttr
[i
].pszObjId
);
2602 *nextData
+= strlen(in
->rgAttr
[i
].pszObjId
) + 1;
2604 if (in
->rgAttr
[i
].cValue
)
2608 out
->rgAttr
[i
].cValue
= in
->rgAttr
[i
].cValue
;
2609 *nextData
= POINTER_ALIGN_DWORD_PTR(*nextData
);
2610 out
->rgAttr
[i
].rgValue
= (PCRYPT_DATA_BLOB
)*nextData
;
2611 *nextData
+= in
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2612 for (j
= 0; j
< in
->rgAttr
[i
].cValue
; j
++)
2613 CRYPT_CopyBlob(&out
->rgAttr
[i
].rgValue
[j
],
2614 &in
->rgAttr
[i
].rgValue
[j
], nextData
);
2620 static DWORD
CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES
*attr
)
2622 DWORD size
= attr
->cAttr
* sizeof(CRYPT_ATTRIBUTE
), i
, j
;
2624 for (i
= 0; i
< attr
->cAttr
; i
++)
2626 if (attr
->rgAttr
[i
].pszObjId
)
2627 size
+= strlen(attr
->rgAttr
[i
].pszObjId
) + 1;
2629 size
= ALIGN_DWORD_PTR(size
);
2630 size
+= attr
->rgAttr
[i
].cValue
* sizeof(CRYPT_DATA_BLOB
);
2631 for (j
= 0; j
< attr
->rgAttr
[i
].cValue
; j
++)
2632 size
+= attr
->rgAttr
[i
].rgValue
[j
].cbData
;
2634 /* align pointer again to be conservative */
2635 size
= ALIGN_DWORD_PTR(size
);
2639 static DWORD
CRYPT_SizeOfKeyIdAsIssuerAndSerial(const CRYPT_DATA_BLOB
*keyId
)
2641 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2644 CERT_RDN rdn
= { 1, &attr
};
2645 CERT_NAME_INFO name
= { 1, &rdn
};
2647 attr
.pszObjId
= oid_key_rdn
;
2648 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2649 attr
.Value
.cbData
= keyId
->cbData
;
2650 attr
.Value
.pbData
= keyId
->pbData
;
2651 if (CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, NULL
, &size
))
2652 size
++; /* Only include size of special zero serial number on success */
2656 static BOOL
CRYPT_CopyKeyIdAsIssuerAndSerial(CERT_NAME_BLOB
*issuer
,
2657 CRYPT_INTEGER_BLOB
*serialNumber
, const CRYPT_DATA_BLOB
*keyId
, DWORD encodedLen
,
2660 static char oid_key_rdn
[] = szOID_KEYID_RDN
;
2662 CERT_RDN rdn
= { 1, &attr
};
2663 CERT_NAME_INFO name
= { 1, &rdn
};
2666 /* Encode special zero serial number */
2667 serialNumber
->cbData
= 1;
2668 serialNumber
->pbData
= *nextData
;
2672 issuer
->pbData
= *nextData
;
2673 attr
.pszObjId
= oid_key_rdn
;
2674 attr
.dwValueType
= CERT_RDN_OCTET_STRING
;
2675 attr
.Value
.cbData
= keyId
->cbData
;
2676 attr
.Value
.pbData
= keyId
->pbData
;
2677 ret
= CryptEncodeObject(X509_ASN_ENCODING
, X509_NAME
, &name
, *nextData
,
2681 *nextData
+= encodedLen
;
2682 issuer
->cbData
= encodedLen
;
2687 static BOOL
CRYPT_CopySignerInfo(void *pvData
, DWORD
*pcbData
,
2688 const CMSG_CMS_SIGNER_INFO
*in
)
2690 DWORD size
= sizeof(CMSG_SIGNER_INFO
), rdnSize
= 0;
2693 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2695 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2697 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2698 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2702 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2705 if (in
->HashAlgorithm
.pszObjId
)
2706 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2707 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2708 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2709 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2710 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2711 size
+= in
->EncryptedHash
.cbData
;
2713 size
= ALIGN_DWORD_PTR(size
);
2714 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2715 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2721 else if (*pcbData
< size
)
2724 SetLastError(ERROR_MORE_DATA
);
2729 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_SIGNER_INFO
);
2730 CMSG_SIGNER_INFO
*out
= pvData
;
2733 out
->dwVersion
= in
->dwVersion
;
2734 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2736 CRYPT_CopyBlob(&out
->Issuer
,
2737 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2738 CRYPT_CopyBlob(&out
->SerialNumber
,
2739 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2742 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2743 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2746 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2748 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2749 &in
->HashEncryptionAlgorithm
, &nextData
);
2750 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2751 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2752 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2753 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2756 TRACE("returning %d\n", ret
);
2760 static BOOL
CRYPT_CopyCMSSignerInfo(void *pvData
, DWORD
*pcbData
,
2761 const CMSG_CMS_SIGNER_INFO
*in
)
2763 DWORD size
= sizeof(CMSG_CMS_SIGNER_INFO
);
2766 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2768 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2770 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2771 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2774 size
+= in
->SignerId
.u
.KeyId
.cbData
;
2775 if (in
->HashAlgorithm
.pszObjId
)
2776 size
+= strlen(in
->HashAlgorithm
.pszObjId
) + 1;
2777 size
+= in
->HashAlgorithm
.Parameters
.cbData
;
2778 if (in
->HashEncryptionAlgorithm
.pszObjId
)
2779 size
+= strlen(in
->HashEncryptionAlgorithm
.pszObjId
) + 1;
2780 size
+= in
->HashEncryptionAlgorithm
.Parameters
.cbData
;
2781 size
+= in
->EncryptedHash
.cbData
;
2783 size
= ALIGN_DWORD_PTR(size
);
2784 size
+= CRYPT_SizeOfAttributes(&in
->AuthAttrs
);
2785 size
+= CRYPT_SizeOfAttributes(&in
->UnauthAttrs
);
2791 else if (*pcbData
< size
)
2794 SetLastError(ERROR_MORE_DATA
);
2799 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CMSG_CMS_SIGNER_INFO
);
2800 CMSG_CMS_SIGNER_INFO
*out
= pvData
;
2802 out
->dwVersion
= in
->dwVersion
;
2803 out
->SignerId
.dwIdChoice
= in
->SignerId
.dwIdChoice
;
2804 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2806 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
2807 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2808 CRYPT_CopyBlob(&out
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
2809 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2812 CRYPT_CopyBlob(&out
->SignerId
.u
.KeyId
, &in
->SignerId
.u
.KeyId
, &nextData
);
2813 CRYPT_CopyAlgorithmId(&out
->HashAlgorithm
, &in
->HashAlgorithm
,
2815 CRYPT_CopyAlgorithmId(&out
->HashEncryptionAlgorithm
,
2816 &in
->HashEncryptionAlgorithm
, &nextData
);
2817 CRYPT_CopyBlob(&out
->EncryptedHash
, &in
->EncryptedHash
, &nextData
);
2818 nextData
= POINTER_ALIGN_DWORD_PTR(nextData
);
2819 CRYPT_CopyAttributes(&out
->AuthAttrs
, &in
->AuthAttrs
, &nextData
);
2820 CRYPT_CopyAttributes(&out
->UnauthAttrs
, &in
->UnauthAttrs
, &nextData
);
2823 TRACE("returning %d\n", ret
);
2827 static BOOL
CRYPT_CopySignerCertInfo(void *pvData
, DWORD
*pcbData
,
2828 const CMSG_CMS_SIGNER_INFO
*in
)
2830 DWORD size
= sizeof(CERT_INFO
), rdnSize
= 0;
2833 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2835 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2837 size
+= in
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
;
2838 size
+= in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
.cbData
;
2842 rdnSize
= CRYPT_SizeOfKeyIdAsIssuerAndSerial(&in
->SignerId
.u
.KeyId
);
2850 else if (*pcbData
< size
)
2853 SetLastError(ERROR_MORE_DATA
);
2858 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2859 CERT_INFO
*out
= pvData
;
2861 memset(out
, 0, sizeof(CERT_INFO
));
2862 if (in
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
2864 CRYPT_CopyBlob(&out
->Issuer
,
2865 &in
->SignerId
.u
.IssuerSerialNumber
.Issuer
, &nextData
);
2866 CRYPT_CopyBlob(&out
->SerialNumber
,
2867 &in
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
, &nextData
);
2871 ret
= CRYPT_CopyKeyIdAsIssuerAndSerial(&out
->Issuer
, &out
->SerialNumber
,
2872 &in
->SignerId
.u
.KeyId
, rdnSize
, &nextData
);
2874 TRACE("returning %d\n", ret
);
2878 static BOOL
CRYPT_CopyRecipientInfo(void *pvData
, DWORD
*pcbData
,
2879 const CERT_ISSUER_SERIAL_NUMBER
*in
)
2881 DWORD size
= sizeof(CERT_INFO
);
2884 TRACE("(%p, %d, %p)\n", pvData
, pvData
? *pcbData
: 0, in
);
2886 size
+= in
->SerialNumber
.cbData
;
2887 size
+= in
->Issuer
.cbData
;
2893 else if (*pcbData
< size
)
2896 SetLastError(ERROR_MORE_DATA
);
2901 LPBYTE nextData
= (BYTE
*)pvData
+ sizeof(CERT_INFO
);
2902 CERT_INFO
*out
= pvData
;
2904 CRYPT_CopyBlob(&out
->SerialNumber
, &in
->SerialNumber
, &nextData
);
2905 CRYPT_CopyBlob(&out
->Issuer
, &in
->Issuer
, &nextData
);
2908 TRACE("returning %d\n", ret
);
2912 static BOOL
CDecodeEnvelopedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2913 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2917 switch (dwParamType
)
2919 case CMSG_TYPE_PARAM
:
2920 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2922 case CMSG_CONTENT_PARAM
:
2923 if (msg
->u
.enveloped_data
.data
)
2924 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2925 msg
->u
.enveloped_data
.content
.pbData
,
2926 msg
->u
.enveloped_data
.content
.cbData
);
2928 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2930 case CMSG_RECIPIENT_COUNT_PARAM
:
2931 if (msg
->u
.enveloped_data
.data
)
2932 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2933 &msg
->u
.enveloped_data
.data
->cRecipientInfo
, sizeof(DWORD
));
2935 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2937 case CMSG_RECIPIENT_INFO_PARAM
:
2938 if (msg
->u
.enveloped_data
.data
)
2940 if (dwIndex
< msg
->u
.enveloped_data
.data
->cRecipientInfo
)
2942 PCMSG_KEY_TRANS_RECIPIENT_INFO recipientInfo
=
2943 &msg
->u
.enveloped_data
.data
->rgRecipientInfo
[dwIndex
];
2945 ret
= CRYPT_CopyRecipientInfo(pvData
, pcbData
,
2946 &recipientInfo
->RecipientId
.u
.IssuerSerialNumber
);
2949 SetLastError(CRYPT_E_INVALID_INDEX
);
2952 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2955 FIXME("unimplemented for %d\n", dwParamType
);
2956 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2961 static BOOL
CDecodeSignedMsg_GetParam(CDecodeMsg
*msg
, DWORD dwParamType
,
2962 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
2966 switch (dwParamType
)
2968 case CMSG_TYPE_PARAM
:
2969 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
, sizeof(msg
->type
));
2971 case CMSG_CONTENT_PARAM
:
2972 if (msg
->u
.signed_data
.info
)
2974 if (!strcmp(msg
->u
.signed_data
.info
->content
.pszObjId
,
2977 CRYPT_DATA_BLOB
*blob
;
2980 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
2981 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
2982 msg
->u
.signed_data
.info
->content
.Content
.cbData
,
2983 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &blob
, &size
);
2986 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
->pbData
,
2992 ret
= CRYPT_CopyParam(pvData
, pcbData
,
2993 msg
->u
.signed_data
.info
->content
.Content
.pbData
,
2994 msg
->u
.signed_data
.info
->content
.Content
.cbData
);
2997 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
2999 case CMSG_INNER_CONTENT_TYPE_PARAM
:
3000 if (msg
->u
.signed_data
.info
)
3001 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3002 msg
->u
.signed_data
.info
->content
.pszObjId
,
3003 strlen(msg
->u
.signed_data
.info
->content
.pszObjId
) + 1);
3005 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3007 case CMSG_SIGNER_COUNT_PARAM
:
3008 if (msg
->u
.signed_data
.info
)
3009 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3010 &msg
->u
.signed_data
.info
->cSignerInfo
, sizeof(DWORD
));
3012 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3014 case CMSG_SIGNER_INFO_PARAM
:
3015 if (msg
->u
.signed_data
.info
)
3017 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3018 SetLastError(CRYPT_E_INVALID_INDEX
);
3020 ret
= CRYPT_CopySignerInfo(pvData
, pcbData
,
3021 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3024 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3026 case CMSG_SIGNER_CERT_INFO_PARAM
:
3027 if (msg
->u
.signed_data
.info
)
3029 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3030 SetLastError(CRYPT_E_INVALID_INDEX
);
3032 ret
= CRYPT_CopySignerCertInfo(pvData
, pcbData
,
3033 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3036 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3038 case CMSG_CERT_COUNT_PARAM
:
3039 if (msg
->u
.signed_data
.info
)
3040 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3041 &msg
->u
.signed_data
.info
->cCertEncoded
, sizeof(DWORD
));
3043 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3045 case CMSG_CERT_PARAM
:
3046 if (msg
->u
.signed_data
.info
)
3048 if (dwIndex
>= msg
->u
.signed_data
.info
->cCertEncoded
)
3049 SetLastError(CRYPT_E_INVALID_INDEX
);
3051 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3052 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].pbData
,
3053 msg
->u
.signed_data
.info
->rgCertEncoded
[dwIndex
].cbData
);
3056 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3058 case CMSG_CRL_COUNT_PARAM
:
3059 if (msg
->u
.signed_data
.info
)
3060 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3061 &msg
->u
.signed_data
.info
->cCrlEncoded
, sizeof(DWORD
));
3063 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3065 case CMSG_CRL_PARAM
:
3066 if (msg
->u
.signed_data
.info
)
3068 if (dwIndex
>= msg
->u
.signed_data
.info
->cCrlEncoded
)
3069 SetLastError(CRYPT_E_INVALID_INDEX
);
3071 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3072 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].pbData
,
3073 msg
->u
.signed_data
.info
->rgCrlEncoded
[dwIndex
].cbData
);
3076 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3078 case CMSG_COMPUTED_HASH_PARAM
:
3079 if (msg
->u
.signed_data
.info
)
3081 if (dwIndex
>= msg
->u
.signed_data
.cSignerHandle
)
3082 SetLastError(CRYPT_E_INVALID_INDEX
);
3084 ret
= CryptGetHashParam(
3085 msg
->u
.signed_data
.signerHandles
[dwIndex
].contentHash
,
3086 HP_HASHVAL
, pvData
, pcbData
, 0);
3089 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3091 case CMSG_ENCODED_SIGNER
:
3092 if (msg
->u
.signed_data
.info
)
3094 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3095 SetLastError(CRYPT_E_INVALID_INDEX
);
3097 ret
= CryptEncodeObjectEx(
3098 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, CMS_SIGNER_INFO
,
3099 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
], 0, NULL
,
3103 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3105 case CMSG_ATTR_CERT_COUNT_PARAM
:
3106 if (msg
->u
.signed_data
.info
)
3108 DWORD attrCertCount
= 0;
3110 ret
= CRYPT_CopyParam(pvData
, pcbData
,
3111 &attrCertCount
, sizeof(DWORD
));
3114 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3116 case CMSG_ATTR_CERT_PARAM
:
3117 if (msg
->u
.signed_data
.info
)
3118 SetLastError(CRYPT_E_INVALID_INDEX
);
3120 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3122 case CMSG_CMS_SIGNER_INFO_PARAM
:
3123 if (msg
->u
.signed_data
.info
)
3125 if (dwIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3126 SetLastError(CRYPT_E_INVALID_INDEX
);
3128 ret
= CRYPT_CopyCMSSignerInfo(pvData
, pcbData
,
3129 &msg
->u
.signed_data
.info
->rgSignerInfo
[dwIndex
]);
3132 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3135 FIXME("unimplemented for %d\n", dwParamType
);
3136 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3141 static BOOL
CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
3142 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3144 CDecodeMsg
*msg
= hCryptMsg
;
3150 ret
= CDecodeHashMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3153 case CMSG_ENVELOPED
:
3154 ret
= CDecodeEnvelopedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3158 ret
= CDecodeSignedMsg_GetParam(msg
, dwParamType
, dwIndex
, pvData
,
3162 switch (dwParamType
)
3164 case CMSG_TYPE_PARAM
:
3165 ret
= CRYPT_CopyParam(pvData
, pcbData
, &msg
->type
,
3170 CRYPT_DATA_BLOB blob
;
3172 ret
= ContextPropertyList_FindProperty(msg
->properties
, dwParamType
,
3175 ret
= CRYPT_CopyParam(pvData
, pcbData
, blob
.pbData
,
3178 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3185 static BOOL
CDecodeHashMsg_VerifyHash(CDecodeMsg
*msg
)
3188 CRYPT_DATA_BLOB hashBlob
;
3190 ret
= ContextPropertyList_FindProperty(msg
->properties
,
3191 CMSG_HASH_DATA_PARAM
, &hashBlob
);
3194 DWORD computedHashSize
= 0;
3196 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
,
3198 if (hashBlob
.cbData
== computedHashSize
)
3200 LPBYTE computedHash
= CryptMemAlloc(computedHashSize
);
3204 ret
= CDecodeHashMsg_GetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
3205 computedHash
, &computedHashSize
);
3208 if (memcmp(hashBlob
.pbData
, computedHash
, hashBlob
.cbData
))
3210 SetLastError(CRYPT_E_HASH_VALUE
);
3214 CryptMemFree(computedHash
);
3218 SetLastError(ERROR_OUTOFMEMORY
);
3224 SetLastError(CRYPT_E_HASH_VALUE
);
3231 static BOOL
CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg
*msg
,
3232 HCRYPTPROV prov
, DWORD signerIndex
, PCERT_PUBLIC_KEY_INFO keyInfo
)
3238 prov
= msg
->crypt_prov
;
3239 ret
= CryptImportPublicKeyInfo(prov
, X509_ASN_ENCODING
, keyInfo
, &key
);
3243 CRYPT_HASH_BLOB reversedHash
;
3245 if (msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].AuthAttrs
.cAttr
)
3246 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].authAttrHash
;
3248 hash
= msg
->u
.signed_data
.signerHandles
[signerIndex
].contentHash
;
3249 ret
= CRYPT_ConstructBlob(&reversedHash
,
3250 &msg
->u
.signed_data
.info
->rgSignerInfo
[signerIndex
].EncryptedHash
);
3253 CRYPT_ReverseBytes(&reversedHash
);
3254 ret
= CryptVerifySignatureW(hash
, reversedHash
.pbData
,
3255 reversedHash
.cbData
, key
, NULL
, 0);
3256 CryptMemFree(reversedHash
.pbData
);
3258 CryptDestroyKey(key
);
3263 static BOOL
CDecodeSignedMsg_VerifySignature(CDecodeMsg
*msg
, PCERT_INFO info
)
3268 if (!msg
->u
.signed_data
.signerHandles
)
3270 SetLastError(NTE_BAD_SIGNATURE
);
3273 for (i
= 0; !ret
&& i
< msg
->u
.signed_data
.info
->cSignerInfo
; i
++)
3275 PCMSG_CMS_SIGNER_INFO signerInfo
=
3276 &msg
->u
.signed_data
.info
->rgSignerInfo
[i
];
3278 if (signerInfo
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
3280 ret
= CertCompareCertificateName(X509_ASN_ENCODING
,
3281 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.Issuer
,
3285 ret
= CertCompareIntegerBlob(
3286 &signerInfo
->SignerId
.u
.IssuerSerialNumber
.SerialNumber
,
3287 &info
->SerialNumber
);
3294 FIXME("signer %d: unimplemented for key id\n", i
);
3298 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, 0, i
,
3299 &info
->SubjectPublicKeyInfo
);
3301 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3306 static BOOL
CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg
*msg
,
3307 PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para
)
3311 if (para
->cbSize
!= sizeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
))
3312 SetLastError(ERROR_INVALID_PARAMETER
);
3313 else if (para
->dwSignerIndex
>= msg
->u
.signed_data
.info
->cSignerInfo
)
3314 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3315 else if (!msg
->u
.signed_data
.signerHandles
)
3316 SetLastError(NTE_BAD_SIGNATURE
);
3319 switch (para
->dwSignerType
)
3321 case CMSG_VERIFY_SIGNER_PUBKEY
:
3322 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
,
3323 para
->hCryptProv
, para
->dwSignerIndex
, para
->pvSigner
);
3325 case CMSG_VERIFY_SIGNER_CERT
:
3327 PCCERT_CONTEXT cert
= para
->pvSigner
;
3329 ret
= CDecodeSignedMsg_VerifySignatureWithKey(msg
, para
->hCryptProv
,
3330 para
->dwSignerIndex
, &cert
->pCertInfo
->SubjectPublicKeyInfo
);
3334 FIXME("unimplemented for signer type %d\n", para
->dwSignerType
);
3335 SetLastError(CRYPT_E_SIGNER_NOT_FOUND
);
3341 static BOOL WINAPI
CRYPT_ImportKeyTrans(
3342 PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm
,
3343 PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara
, DWORD dwFlags
,
3344 void *pvReserved
, HCRYPTKEY
*phContentEncryptKey
)
3349 ret
= CryptGetUserKey(pKeyTransDecryptPara
->hCryptProv
,
3350 pKeyTransDecryptPara
->dwKeySpec
? pKeyTransDecryptPara
->dwKeySpec
:
3351 AT_KEYEXCHANGE
, &key
);
3354 CMSG_KEY_TRANS_RECIPIENT_INFO
*info
=
3355 &pKeyTransDecryptPara
->pKeyTrans
[pKeyTransDecryptPara
->dwRecipientIndex
];
3356 CRYPT_DATA_BLOB
*encryptedKey
= &info
->EncryptedKey
;
3357 DWORD size
= encryptedKey
->cbData
+ sizeof(BLOBHEADER
) + sizeof(ALG_ID
);
3358 BYTE
*keyBlob
= CryptMemAlloc(size
);
3362 DWORD i
, k
= size
- 1;
3363 BLOBHEADER
*blobHeader
= (BLOBHEADER
*)keyBlob
;
3364 ALG_ID
*algID
= (ALG_ID
*)(keyBlob
+ sizeof(BLOBHEADER
));
3366 blobHeader
->bType
= SIMPLEBLOB
;
3367 blobHeader
->bVersion
= CUR_BLOB_VERSION
;
3368 blobHeader
->reserved
= 0;
3369 blobHeader
->aiKeyAlg
= CertOIDToAlgId(
3370 pContentEncryptionAlgorithm
->pszObjId
);
3371 *algID
= CertOIDToAlgId(info
->KeyEncryptionAlgorithm
.pszObjId
);
3372 for (i
= 0; i
< encryptedKey
->cbData
; ++i
, --k
)
3373 keyBlob
[k
] = encryptedKey
->pbData
[i
];
3375 ret
= CryptImportKey(pKeyTransDecryptPara
->hCryptProv
, keyBlob
,
3376 size
, key
, 0, phContentEncryptKey
);
3377 CryptMemFree(keyBlob
);
3381 CryptDestroyKey(key
);
3386 static BOOL
CRYPT_ImportEncryptedKey(PCRYPT_ALGORITHM_IDENTIFIER contEncrAlg
,
3387 PCMSG_CTRL_DECRYPT_PARA para
, PCMSG_KEY_TRANS_RECIPIENT_INFO info
,
3390 static HCRYPTOIDFUNCSET set
= NULL
;
3391 PFN_CMSG_IMPORT_KEY_TRANS importKeyFunc
= NULL
;
3392 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3393 CMSG_CTRL_KEY_TRANS_DECRYPT_PARA decryptPara
;
3396 memset(&decryptPara
, 0, sizeof(decryptPara
));
3397 decryptPara
.cbSize
= sizeof(decryptPara
);
3398 decryptPara
.hCryptProv
= para
->hCryptProv
;
3399 decryptPara
.dwKeySpec
= para
->dwKeySpec
;
3400 decryptPara
.pKeyTrans
= info
;
3401 decryptPara
.dwRecipientIndex
= para
->dwRecipientIndex
;
3404 set
= CryptInitOIDFunctionSet(CMSG_OID_IMPORT_KEY_TRANS_FUNC
, 0);
3405 CryptGetOIDFunctionAddress(set
, X509_ASN_ENCODING
, contEncrAlg
->pszObjId
, 0,
3406 (void **)&importKeyFunc
, &hFunc
);
3408 importKeyFunc
= CRYPT_ImportKeyTrans
;
3409 ret
= importKeyFunc(contEncrAlg
, &decryptPara
, 0, NULL
, key
);
3411 CryptFreeOIDFunctionAddress(hFunc
, 0);
3415 static BOOL
CDecodeEnvelopedMsg_CrtlDecrypt(CDecodeMsg
*msg
,
3416 PCMSG_CTRL_DECRYPT_PARA para
)
3419 CEnvelopedDecodeMsg
*enveloped_data
= &msg
->u
.enveloped_data
;
3420 CRYPT_ENVELOPED_DATA
*data
= enveloped_data
->data
;
3422 if (para
->cbSize
!= sizeof(CMSG_CTRL_DECRYPT_PARA
))
3423 SetLastError(E_INVALIDARG
);
3425 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3426 else if (para
->dwRecipientIndex
>= data
->cRecipientInfo
)
3427 SetLastError(CRYPT_E_INVALID_INDEX
);
3428 else if (enveloped_data
->decrypted
)
3429 SetLastError(CRYPT_E_ALREADY_DECRYPTED
);
3430 else if (!para
->hCryptProv
)
3431 SetLastError(ERROR_INVALID_PARAMETER
);
3432 else if (enveloped_data
->content
.cbData
)
3436 ret
= CRYPT_ImportEncryptedKey(
3437 &data
->encryptedContentInfo
.contentEncryptionAlgorithm
, para
,
3438 data
->rgRecipientInfo
, &key
);
3441 ret
= CryptDecrypt(key
, 0, TRUE
, 0, enveloped_data
->content
.pbData
,
3442 &enveloped_data
->content
.cbData
);
3443 CryptDestroyKey(key
);
3449 enveloped_data
->decrypted
= TRUE
;
3453 static BOOL
CDecodeMsg_Control(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3454 DWORD dwCtrlType
, const void *pvCtrlPara
)
3456 CDecodeMsg
*msg
= hCryptMsg
;
3461 case CMSG_CTRL_VERIFY_SIGNATURE
:
3465 ret
= CDecodeSignedMsg_VerifySignature(msg
, (PCERT_INFO
)pvCtrlPara
);
3468 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3471 case CMSG_CTRL_DECRYPT
:
3474 case CMSG_ENVELOPED
:
3475 ret
= CDecodeEnvelopedMsg_CrtlDecrypt(msg
,
3476 (PCMSG_CTRL_DECRYPT_PARA
)pvCtrlPara
);
3477 if (ret
&& (dwFlags
& CMSG_CRYPT_RELEASE_CONTEXT_FLAG
))
3478 msg
->u
.enveloped_data
.crypt_prov
=
3479 ((PCMSG_CTRL_DECRYPT_PARA
)pvCtrlPara
)->hCryptProv
;
3482 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3485 case CMSG_CTRL_VERIFY_HASH
:
3489 ret
= CDecodeHashMsg_VerifyHash(msg
);
3492 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3495 case CMSG_CTRL_VERIFY_SIGNATURE_EX
:
3499 ret
= CDecodeSignedMsg_VerifySignatureEx(msg
,
3500 (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
)pvCtrlPara
);
3503 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
3507 SetLastError(CRYPT_E_CONTROL_TYPE
);
3512 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
3513 DWORD dwMsgType
, HCRYPTPROV_LEGACY hCryptProv
, PCERT_INFO pRecipientInfo
,
3514 PCMSG_STREAM_INFO pStreamInfo
)
3518 TRACE("(%08x, %08x, %08x, %08lx, %p, %p)\n", dwMsgEncodingType
,
3519 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
3521 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
3523 SetLastError(E_INVALIDARG
);
3526 msg
= CryptMemAlloc(sizeof(CDecodeMsg
));
3529 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
3530 CDecodeMsg_Close
, CDecodeMsg_GetParam
, CDecodeMsg_Update
,
3531 CDecodeMsg_Control
);
3532 msg
->type
= dwMsgType
;
3534 msg
->crypt_prov
= hCryptProv
;
3537 msg
->crypt_prov
= CRYPT_GetDefaultProvider();
3538 msg
->base
.open_flags
&= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG
;
3540 memset(&msg
->u
, 0, sizeof(msg
->u
));
3541 msg
->msg_data
.cbData
= 0;
3542 msg
->msg_data
.pbData
= NULL
;
3543 msg
->detached_data
.cbData
= 0;
3544 msg
->detached_data
.pbData
= NULL
;
3545 msg
->properties
= ContextPropertyList_Create();
3550 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
3552 TRACE("(%p)\n", hCryptMsg
);
3556 CryptMsgBase
*msg
= hCryptMsg
;
3558 InterlockedIncrement(&msg
->ref
);
3563 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
3565 TRACE("(%p)\n", hCryptMsg
);
3569 CryptMsgBase
*msg
= hCryptMsg
;
3571 if (InterlockedDecrement(&msg
->ref
) == 0)
3573 TRACE("freeing %p\n", msg
);
3582 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
3583 DWORD cbData
, BOOL fFinal
)
3585 CryptMsgBase
*msg
= hCryptMsg
;
3587 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
3589 return msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
3592 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
3593 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
3595 CryptMsgBase
*msg
= hCryptMsg
;
3597 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
3599 return msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);
3602 BOOL WINAPI
CryptMsgControl(HCRYPTMSG hCryptMsg
, DWORD dwFlags
,
3603 DWORD dwCtrlType
, const void *pvCtrlPara
)
3605 CryptMsgBase
*msg
= hCryptMsg
;
3607 TRACE("(%p, %08x, %d, %p)\n", hCryptMsg
, dwFlags
, dwCtrlType
,
3609 return msg
->control(hCryptMsg
, dwFlags
, dwCtrlType
, pvCtrlPara
);
3612 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
3613 DWORD dwSignerIndex
)
3615 CERT_INFO
*certInfo
= NULL
;
3618 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
3621 certInfo
= CryptMemAlloc(size
);
3624 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
3625 dwSignerIndex
, certInfo
, &size
))
3627 CryptMemFree(certInfo
);
3635 BOOL WINAPI
CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg
, DWORD cSignerStore
,
3636 HCERTSTORE
*rghSignerStore
, DWORD dwFlags
, PCCERT_CONTEXT
*ppSigner
,
3637 DWORD
*pdwSignerIndex
)
3640 DWORD i
, signerIndex
= 0;
3641 PCCERT_CONTEXT signerCert
= NULL
;
3644 TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg
, cSignerStore
,
3645 rghSignerStore
, dwFlags
, ppSigner
, pdwSignerIndex
);
3647 /* Clear output parameters */
3650 if (pdwSignerIndex
&& !(dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
))
3651 *pdwSignerIndex
= 0;
3653 /* Create store to search for signer certificates */
3654 store
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
3655 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
3656 if (!(dwFlags
& CMSG_TRUSTED_SIGNER_FLAG
))
3658 HCERTSTORE msgStore
= CertOpenStore(CERT_STORE_PROV_MSG
, 0, 0, 0,
3661 CertAddStoreToCollection(store
, msgStore
, 0, 0);
3662 CertCloseStore(msgStore
, 0);
3664 for (i
= 0; i
< cSignerStore
; i
++)
3665 CertAddStoreToCollection(store
, rghSignerStore
[i
], 0, 0);
3667 /* Find signer cert */
3668 if (dwFlags
& CMSG_USE_SIGNER_INDEX_FLAG
)
3670 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3675 signerIndex
= *pdwSignerIndex
;
3676 signerCert
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
,
3677 0, CERT_FIND_SUBJECT_CERT
, signer
, NULL
);
3678 CryptMemFree(signer
);
3683 DWORD count
, size
= sizeof(count
);
3685 if (CryptMsgGetParam(hCryptMsg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
,
3688 for (i
= 0; !signerCert
&& i
< count
; i
++)
3690 CERT_INFO
*signer
= CRYPT_GetSignerCertInfoFromMsg(hCryptMsg
,
3695 signerCert
= CertFindCertificateInStore(store
,
3696 X509_ASN_ENCODING
, 0, CERT_FIND_SUBJECT_CERT
, signer
,
3700 CryptMemFree(signer
);
3705 SetLastError(CRYPT_E_NO_TRUSTED_SIGNER
);
3709 if (!(dwFlags
& CMSG_SIGNER_ONLY_FLAG
))
3710 ret
= CryptMsgControl(hCryptMsg
, 0, CMSG_CTRL_VERIFY_SIGNATURE
,
3711 signerCert
->pCertInfo
);
3717 *ppSigner
= CertDuplicateCertificateContext(signerCert
);
3719 *pdwSignerIndex
= signerIndex
;
3721 CertFreeCertificateContext(signerCert
);
3724 CertCloseStore(store
, 0);
3728 BOOL WINAPI
CryptMsgVerifyCountersignatureEncodedEx(HCRYPTPROV_LEGACY hCryptProv
,
3729 DWORD dwEncodingType
, PBYTE pbSignerInfo
, DWORD cbSignerInfo
,
3730 PBYTE pbSignerInfoCountersignature
, DWORD cbSignerInfoCountersignature
,
3731 DWORD dwSignerType
, void *pvSigner
, DWORD dwFlags
, void *pvReserved
)
3733 FIXME("(%08lx, %08x, %p, %d, %p, %d, %d, %p, %08x, %p): stub\n", hCryptProv
,
3734 dwEncodingType
, pbSignerInfo
, cbSignerInfo
, pbSignerInfoCountersignature
,
3735 cbSignerInfoCountersignature
, dwSignerType
, pvSigner
, dwFlags
, pvReserved
);
3739 BOOL WINAPI
CryptMsgEncodeAndSignCTL(DWORD dwMsgEncodingType
,
3740 PCTL_INFO pCtlInfo
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3741 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3747 TRACE("(%08x, %p, %p, %08x, %p, %p)\n", dwMsgEncodingType
, pCtlInfo
,
3748 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3752 FIXME("unimplemented for flags %08x\n", dwFlags
);
3755 if ((ret
= CryptEncodeObjectEx(dwMsgEncodingType
, PKCS_CTL
, pCtlInfo
,
3756 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &pbCtlContent
, &cbCtlContent
)))
3758 ret
= CryptMsgSignCTL(dwMsgEncodingType
, pbCtlContent
, cbCtlContent
,
3759 pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3760 LocalFree(pbCtlContent
);
3765 BOOL WINAPI
CryptMsgSignCTL(DWORD dwMsgEncodingType
, BYTE
*pbCtlContent
,
3766 DWORD cbCtlContent
, PCMSG_SIGNED_ENCODE_INFO pSignInfo
, DWORD dwFlags
,
3767 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3769 static char oid_ctl
[] = szOID_CTL
;
3773 TRACE("(%08x, %p, %d, %p, %08x, %p, %p)\n", dwMsgEncodingType
,
3774 pbCtlContent
, cbCtlContent
, pSignInfo
, dwFlags
, pbEncoded
, pcbEncoded
);
3778 FIXME("unimplemented for flags %08x\n", dwFlags
);
3781 msg
= CryptMsgOpenToEncode(dwMsgEncodingType
, 0, CMSG_SIGNED
, pSignInfo
,
3785 ret
= CryptMsgUpdate(msg
, pbCtlContent
, cbCtlContent
, TRUE
);
3787 ret
= CryptMsgGetParam(msg
, CMSG_CONTENT_PARAM
, 0, pbEncoded
,