Module: wine Branch: master Commit: 6ad5416f32dae5e436a55d1a6fac871d533abf30 URL: http://source.winehq.org/git/wine.git/?a=commit;h=6ad5416f32dae5e436a55d1a6f...
Author: Alexander Morozov amorozov@etersoft.ru Date: Wed Dec 1 14:40:27 2010 +0300
crypt32: Implement getting content of an enveloped message.
---
dlls/crypt32/crypt32_private.h | 18 +++++++++++++ dlls/crypt32/encode.c | 55 ++++++++++++++++++++++++++++++++++++++++ dlls/crypt32/msg.c | 55 +++++++++++++++++++++++++++++++++++++-- dlls/crypt32/tests/msg.c | 2 - 4 files changed, 125 insertions(+), 5 deletions(-)
diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index 36ee3e2..a4b9aff 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -82,6 +82,24 @@ typedef struct _CRYPT_DIGESTED_DATA BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData, void *pvData, DWORD *pcbData);
+typedef struct _CRYPT_ENCRYPTED_CONTENT_INFO +{ + LPSTR contentType; + CRYPT_ALGORITHM_IDENTIFIER contentEncryptionAlgorithm; + CRYPT_DATA_BLOB encryptedContent; +} CRYPT_ENCRYPTED_CONTENT_INFO; + +typedef struct _CRYPT_ENVELOPED_DATA +{ + DWORD version; + DWORD cRecipientInfo; + PCMSG_KEY_TRANS_RECIPIENT_INFO rgRecipientInfo; + CRYPT_ENCRYPTED_CONTENT_INFO encryptedContentInfo; +} CRYPT_ENVELOPED_DATA; + +BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData, + void *pvData, DWORD *pcbData); + typedef struct _CRYPT_SIGNED_INFO { DWORD version; diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c index 3beab84..5d6affe 100644 --- a/dlls/crypt32/encode.c +++ b/dlls/crypt32/encode.c @@ -4293,6 +4293,61 @@ BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData, return ret; }
+static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType, + LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, + PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) +{ + const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo; + struct AsnEncodeSequenceItem items[] = { + { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, + { &info->RecipientId.u.IssuerSerialNumber, + CRYPT_AsnEncodeIssuerSerialNumber, 0 }, + { &info->KeyEncryptionAlgorithm, + CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, + { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 }, + }; + + return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, + sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, + pcbEncoded); +} + +static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType, + LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, + PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) +{ + const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo; + struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0, + &info->encryptedContent, CRYPT_AsnEncodeOctets }; + struct AsnEncodeSequenceItem items[] = { + { info->contentType, CRYPT_AsnEncodeOid, 0 }, + { &info->contentEncryptionAlgorithm, + CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, + { &swapped, CRYPT_AsnEncodeSwapTag, 0 }, + }; + + return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, + sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, + pcbEncoded); +} + +BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData, + void *pvData, DWORD *pcbData) +{ + struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo, + envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0, + CRYPT_AsnEncodeRecipientInfo }; + struct AsnEncodeSequenceItem items[] = { + { &envelopedData->version, CRYPT_AsnEncodeInt, 0 }, + { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 }, + { &envelopedData->encryptedContentInfo, + CRYPT_AsnEncodeEncryptedContentInfo, 0 }, + }; + + return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, + sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData); +} + static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType, LPCSTR lpszStructType) { diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index 2b93a5b..f083c53 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -1785,9 +1785,58 @@ static void CEnvelopedEncodeMsg_Close(HCRYPTMSG hCryptMsg) static BOOL CEnvelopedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex, void *pvData, DWORD *pcbData) { - FIXME("(%p, %d, %d, %p, %p): stub\n", hCryptMsg, dwParamType, dwIndex, - pvData, pcbData); - return FALSE; + CEnvelopedEncodeMsg *msg = hCryptMsg; + BOOL ret = FALSE; + + switch (dwParamType) + { + case CMSG_BARE_CONTENT_PARAM: + if (msg->base.streamed) + SetLastError(E_INVALIDARG); + else + { + char oid_rsa_data[] = szOID_RSA_data; + CRYPT_ENVELOPED_DATA envelopedData = { + CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION, msg->cRecipientInfo, + msg->recipientInfo, { oid_rsa_data, msg->algo, msg->data } + }; + + ret = CRYPT_AsnEncodePKCSEnvelopedData(&envelopedData, pvData, + pcbData); + } + break; + case CMSG_CONTENT_PARAM: + { + CRYPT_CONTENT_INFO info; + + ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL, + &info.Content.cbData); + if (ret) + { + info.Content.pbData = CryptMemAlloc(info.Content.cbData); + if (info.Content.pbData) + { + ret = CryptMsgGetParam(hCryptMsg, CMSG_BARE_CONTENT_PARAM, 0, + info.Content.pbData, &info.Content.cbData); + if (ret) + { + char oid_rsa_enveloped[] = szOID_RSA_envelopedData; + + info.pszObjId = oid_rsa_enveloped; + ret = CryptEncodeObjectEx(X509_ASN_ENCODING, + PKCS_CONTENT_INFO, &info, 0, NULL, pvData, pcbData); + } + CryptMemFree(info.Content.pbData); + } + else + ret = FALSE; + } + break; + } + default: + SetLastError(CRYPT_E_INVALID_MSG_TYPE); + } + return ret; }
static BOOL CEnvelopedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c index 9ffae52..e32690b 100644 --- a/dlls/crypt32/tests/msg.c +++ b/dlls/crypt32/tests/msg.c @@ -2248,11 +2248,9 @@ static void test_enveloped_msg_encoding(void) "CryptMsgOpenToEncode failed: %08x\n", GetLastError()); if (msg) { - todo_wine check_param("enveloped empty bare content", msg, CMSG_BARE_CONTENT_PARAM, envelopedEmptyBareContent, sizeof(envelopedEmptyBareContent)); - todo_wine check_param("enveloped empty content", msg, CMSG_CONTENT_PARAM, envelopedEmptyContent, sizeof(envelopedEmptyContent)); CryptMsgClose(msg);