[Wine-devel] Eter's patch is applied to winehq repo 12/17/10
builder на builder.office.etersoft.ru
builder на builder.office.etersoft.ru
Пт Дек 17 21:20:46 MSK 2010
New Etersoft's patches since last build time:
commit f44ae748c0015c144f6a08702cda9b5f3b2bed8b
Author: Alexander Morozov <amorozov на etersoft.ru>
crypt32: Implement getting content and some parameters from a decoded enveloped message.
commit dd75ab38c640e0be5a513f3051b0bdaccc7cc668
Author: Alexander Morozov <amorozov на etersoft.ru>
crypt32: Implement decoding enveloped messages.
commit 60be01f16d142fd88371cb3e45eca50b6d50b81f
Author: Alexander Morozov <amorozov на etersoft.ru>
wincrypt.h: Define PFN_CMSG_IMPORT_KEY_TRANS callback function.
---
commit f44ae748c0015c144f6a08702cda9b5f3b2bed8b
Author: Alexander Morozov <amorozov на etersoft.ru>
Date: Wed Dec 15 17:51:37 2010 +0300
crypt32: Implement getting content and some parameters from a decoded enveloped message.
diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c
index d85d2a0..b083d26 100644
--- a/dlls/crypt32/msg.c
+++ b/dlls/crypt32/msg.c
@@ -2881,6 +2881,89 @@ static BOOL CRYPT_CopySignerCertInfo(void *pvData, DWORD *pcbData,
return ret;
}
+static BOOL CRYPT_CopyRecipientInfo(void *pvData, DWORD *pcbData,
+ const CERT_ISSUER_SERIAL_NUMBER *in)
+{
+ DWORD size = sizeof(CERT_INFO);
+ BOOL ret;
+
+ TRACE("(%p, %d, %p)\n", pvData, pvData ? *pcbData : 0, in);
+
+ size += in->SerialNumber.cbData;
+ size += in->Issuer.cbData;
+ if (!pvData)
+ {
+ *pcbData = size;
+ ret = TRUE;
+ }
+ else if (*pcbData < size)
+ {
+ *pcbData = size;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ LPBYTE nextData = (BYTE *)pvData + sizeof(CERT_INFO);
+ CERT_INFO *out = pvData;
+
+ CRYPT_CopyBlob(&out->SerialNumber, &in->SerialNumber, &nextData);
+ CRYPT_CopyBlob(&out->Issuer, &in->Issuer, &nextData);
+ ret = TRUE;
+ }
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL CDecodeEnvelopedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType,
+ DWORD dwIndex, void *pvData, DWORD *pcbData)
+{
+ BOOL ret = FALSE;
+
+ switch (dwParamType)
+ {
+ case CMSG_TYPE_PARAM:
+ ret = CRYPT_CopyParam(pvData, pcbData, &msg->type, sizeof(msg->type));
+ break;
+ case CMSG_CONTENT_PARAM:
+ if (msg->u.enveloped_data.data)
+ ret = CRYPT_CopyParam(pvData, pcbData,
+ msg->u.enveloped_data.content.pbData,
+ msg->u.enveloped_data.content.cbData);
+ else
+ SetLastError(CRYPT_E_INVALID_MSG_TYPE);
+ break;
+ case CMSG_RECIPIENT_COUNT_PARAM:
+ if (msg->u.enveloped_data.data)
+ ret = CRYPT_CopyParam(pvData, pcbData,
+ &msg->u.enveloped_data.data->cRecipientInfo, sizeof(DWORD));
+ else
+ SetLastError(CRYPT_E_INVALID_MSG_TYPE);
+ break;
+ case CMSG_RECIPIENT_INFO_PARAM:
+ if (msg->u.enveloped_data.data)
+ {
+ if (dwIndex < msg->u.enveloped_data.data->cRecipientInfo)
+ {
+ PCMSG_KEY_TRANS_RECIPIENT_INFO recipientInfo =
+ &msg->u.enveloped_data.data->rgRecipientInfo[dwIndex];
+
+ ret = CRYPT_CopyRecipientInfo(pvData, pcbData,
+ &recipientInfo->RecipientId.u.IssuerSerialNumber);
+ }
+ else
+ SetLastError(CRYPT_E_INVALID_INDEX);
+ }
+ else
+ SetLastError(CRYPT_E_INVALID_MSG_TYPE);
+ break;
+ default:
+ FIXME("unimplemented for %d\n", dwParamType);
+ SetLastError(CRYPT_E_INVALID_MSG_TYPE);
+ }
+ return ret;
+}
+
static BOOL CDecodeSignedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType,
DWORD dwIndex, void *pvData, DWORD *pcbData)
{
@@ -3073,6 +3156,10 @@ static BOOL CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
ret = CDecodeHashMsg_GetParam(msg, dwParamType, dwIndex, pvData,
pcbData);
break;
+ case CMSG_ENVELOPED:
+ ret = CDecodeEnvelopedMsg_GetParam(msg, dwParamType, dwIndex, pvData,
+ pcbData);
+ break;
case CMSG_SIGNED:
ret = CDecodeSignedMsg_GetParam(msg, dwParamType, dwIndex, pvData,
pcbData);
diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c
index 20ad5c9..77b468c 100644
--- a/dlls/crypt32/tests/msg.c
+++ b/dlls/crypt32/tests/msg.c
@@ -3057,7 +3057,6 @@ static void test_decode_msg_get_param(void)
NULL);
CryptMsgUpdate(msg, envelopedEmptyBareContent,
sizeof(envelopedEmptyBareContent), TRUE);
- todo_wine
check_param("enveloped empty bare content", msg, CMSG_CONTENT_PARAM, NULL,
0);
CryptMsgClose(msg);
@@ -3065,7 +3064,6 @@ static void test_decode_msg_get_param(void)
msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
CryptMsgUpdate(msg, envelopedEmptyContent, sizeof(envelopedEmptyContent),
TRUE);
- todo_wine
check_param("enveloped empty content", msg, CMSG_CONTENT_PARAM, NULL, 0);
CryptMsgClose(msg);
@@ -3080,7 +3078,6 @@ static void test_decode_msg_get_param(void)
msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
CryptMsgUpdate(msg, envelopedMessage, sizeof(envelopedMessage), TRUE);
- todo_wine
check_param("enveloped message before decrypting", msg, CMSG_CONTENT_PARAM,
envelopedMessage + sizeof(envelopedMessage) - 4, 4);
if (key)
@@ -3094,7 +3091,6 @@ static void test_decode_msg_get_param(void)
ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
ok(!ret && GetLastError() == CRYPT_E_ALREADY_DECRYPTED,
"expected CRYPT_E_ALREADY_DECRYPTED, got %08x\n", GetLastError());
- todo_wine
check_param("enveloped message", msg, CMSG_CONTENT_PARAM, msgData,
sizeof(msgData));
}
@@ -3106,7 +3102,6 @@ static void test_decode_msg_get_param(void)
NULL);
CryptMsgUpdate(msg, envelopedBareMessage, sizeof(envelopedBareMessage),
TRUE);
- todo_wine
check_param("enveloped bare message before decrypting", msg,
CMSG_CONTENT_PARAM, envelopedBareMessage +
sizeof(envelopedBareMessage) - 4, 4);
@@ -3116,7 +3111,6 @@ static void test_decode_msg_get_param(void)
SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
ok(ret, "CryptMsgControl failed: %08x\n", GetLastError());
- todo_wine
check_param("enveloped bare message", msg, CMSG_CONTENT_PARAM, msgData,
sizeof(msgData));
}
@@ -3132,21 +3126,17 @@ static void test_decode_msg_get_param(void)
CryptMsgUpdate(msg, envelopedMessageWith3Recps,
sizeof(envelopedMessageWith3Recps), TRUE);
value = 3;
- todo_wine
check_param("recipient count", msg, CMSG_RECIPIENT_COUNT_PARAM,
(const BYTE *)&value, sizeof(value));
size = 0;
SetLastError(0xdeadbeef);
ret = CryptMsgGetParam(msg, CMSG_RECIPIENT_INFO_PARAM, 3, NULL, &size);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
"expected CRYPT_E_INVALID_INDEX, got %08x\n", GetLastError());
size = 0;
SetLastError(0xdeadbeef);
ret = CryptMsgGetParam(msg, CMSG_RECIPIENT_INFO_PARAM, 2, NULL, &size);
- todo_wine
ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
- todo_wine
ok(size >= 142, "unexpected size: %u\n", size);
if (ret)
buf = CryptMemAlloc(size);
@@ -3158,18 +3148,13 @@ static void test_decode_msg_get_param(void)
SetLastError(0xdeadbeef);
ret = CryptMsgGetParam(msg, CMSG_RECIPIENT_INFO_PARAM, 2, buf, &size);
- todo_wine
ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
- todo_wine
ok(certInfo->SerialNumber.cbData == sizeof(serialNumber),
"unexpected serial number size: %u\n", certInfo->SerialNumber.cbData);
- todo_wine
ok(!memcmp(certInfo->SerialNumber.pbData, serialNumber,
sizeof(serialNumber)), "unexpected serial number\n");
- todo_wine
ok(certInfo->Issuer.cbData == sizeof(issuer),
"unexpected issuer size: %u\n", certInfo->Issuer.cbData);
- todo_wine
ok(!memcmp(certInfo->Issuer.pbData, issuer, sizeof(issuer)),
"unexpected issuer\n");
CryptMemFree(buf);
commit dd75ab38c640e0be5a513f3051b0bdaccc7cc668
Author: Alexander Morozov <amorozov на etersoft.ru>
Date: Wed Dec 15 17:35:29 2010 +0300
crypt32: Implement decoding enveloped messages.
diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h
index a4b9aff..65a9cd2 100644
--- a/dlls/crypt32/crypt32_private.h
+++ b/dlls/crypt32/crypt32_private.h
@@ -100,6 +100,10 @@ typedef struct _CRYPT_ENVELOPED_DATA
BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData,
void *pvData, DWORD *pcbData);
+BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
+ CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData);
+
typedef struct _CRYPT_SIGNED_INFO
{
DWORD version;
diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c
index a5602ac..62231cd 100644
--- a/dlls/crypt32/decode.c
+++ b/dlls/crypt32/decode.c
@@ -5569,6 +5569,124 @@ BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
return ret;
}
+static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
+{
+ BOOL ret;
+ CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, dwVersion),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
+ RecipientId.u.IssuerSerialNumber), CRYPT_AsnDecodeIssuerSerialNumber,
+ sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE,
+ offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
+ RecipientId.u.IssuerSerialNumber.Issuer.pbData), 0 },
+ { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
+ KeyEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
+ offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
+ KeyEncryptionAlgorithm.pszObjId), 0 },
+ { ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey),
+ CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
+ offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 },
+ };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, info ? info->RecipientId.u.IssuerSerialNumber.Issuer.pbData :
+ NULL);
+ if (info)
+ info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL CRYPT_DecodeRecipientInfoArray(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
+ offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo),
+ offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo),
+ MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
+ CRYPT_AsnDecodeRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), TRUE,
+ offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
+ RecipientId.u.IssuerSerialNumber.Issuer.pbData) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
+ contentType), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
+ FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
+ contentType), 0 },
+ { ASN_SEQUENCEOF, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
+ contentEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
+ sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
+ offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
+ contentEncryptionAlgorithm.pszObjId), 0 },
+ { ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
+ encryptedContent), CRYPT_AsnDecodeOctetsInternal,
+ sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
+ offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) },
+ };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, info ? info->contentType : NULL);
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
+ CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData)
+{
+ BOOL ret;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(CRYPT_ENVELOPED_DATA, version),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA,
+ cRecipientInfo), CRYPT_DecodeRecipientInfoArray,
+ MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
+ FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), 0 },
+ { ASN_SEQUENCEOF, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo),
+ CRYPT_AsnDecodeEncryptedContentInfo,
+ sizeof(CRYPT_ENCRYPTED_CONTENT_INFO), FALSE, TRUE,
+ offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 },
+ };
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, envelopedData, *pcbEnvelopedData);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData,
+ pcbEnvelopedData, NULL, NULL);
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
LPCSTR lpszStructType)
{
diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c
index 1c5cca4..d85d2a0 100644
--- a/dlls/crypt32/msg.c
+++ b/dlls/crypt32/msg.c
@@ -2045,14 +2045,23 @@ HCRYPTMSG WINAPI CryptMsgOpenToEncode(DWORD dwMsgEncodingType, DWORD dwFlags,
return msg;
}
+typedef struct _CEnvelopedDecodeMsg
+{
+ CRYPT_ENVELOPED_DATA *data;
+ HCRYPTPROV crypt_prov;
+ CRYPT_DATA_BLOB content;
+ BOOL decrypted;
+} CEnvelopedDecodeMsg;
+
typedef struct _CDecodeMsg
{
CryptMsgBase base;
DWORD type;
HCRYPTPROV crypt_prov;
union {
- HCRYPTHASH hash;
- CSignedMsgData signed_data;
+ HCRYPTHASH hash;
+ CSignedMsgData signed_data;
+ CEnvelopedDecodeMsg enveloped_data;
} u;
CRYPT_DATA_BLOB msg_data;
CRYPT_DATA_BLOB detached_data;
@@ -2071,6 +2080,12 @@ static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg)
if (msg->u.hash)
CryptDestroyHash(msg->u.hash);
break;
+ case CMSG_ENVELOPED:
+ if (msg->u.enveloped_data.crypt_prov)
+ CryptReleaseContext(msg->u.enveloped_data.crypt_prov, 0);
+ LocalFree(msg->u.enveloped_data.data);
+ CryptMemFree(msg->u.enveloped_data.content.pbData);
+ break;
case CMSG_SIGNED:
if (msg->u.signed_data.info)
{
@@ -2203,6 +2218,21 @@ static BOOL CDecodeMsg_DecodeHashedContent(CDecodeMsg *msg,
return ret;
}
+static BOOL CDecodeMsg_DecodeEnvelopedContent(CDecodeMsg *msg,
+ const CRYPT_DER_BLOB *blob)
+{
+ BOOL ret;
+ CRYPT_ENVELOPED_DATA *envelopedData;
+ DWORD size;
+
+ ret = CRYPT_AsnDecodePKCSEnvelopedData(blob->pbData, blob->cbData,
+ CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_ENVELOPED_DATA *)&envelopedData,
+ &size);
+ if (ret)
+ msg->u.enveloped_data.data = envelopedData;
+ return ret;
+}
+
static BOOL CDecodeMsg_DecodeSignedContent(CDecodeMsg *msg,
const CRYPT_DER_BLOB *blob)
{
@@ -2239,8 +2269,8 @@ static BOOL CDecodeMsg_DecodeContent(CDecodeMsg *msg, const CRYPT_DER_BLOB *blob
msg->type = CMSG_HASHED;
break;
case CMSG_ENVELOPED:
- FIXME("unimplemented for type CMSG_ENVELOPED\n");
- ret = TRUE;
+ if ((ret = CDecodeMsg_DecodeEnvelopedContent(msg, blob)))
+ msg->type = CMSG_ENVELOPED;
break;
case CMSG_SIGNED:
if ((ret = CDecodeMsg_DecodeSignedContent(msg, blob)))
@@ -2316,6 +2346,20 @@ static BOOL CDecodeMsg_FinalizeHashedContent(CDecodeMsg *msg,
return ret;
}
+static BOOL CDecodeMsg_FinalizeEnvelopedContent(CDecodeMsg *msg,
+ CRYPT_DER_BLOB *blob)
+{
+ CRYPT_DATA_BLOB *content;
+
+ if (msg->base.open_flags & CMSG_DETACHED_FLAG)
+ content = &msg->detached_data;
+ else
+ content =
+ &msg->u.enveloped_data.data->encryptedContentInfo.encryptedContent;
+
+ return CRYPT_ConstructBlob(&msg->u.enveloped_data.content, content);
+}
+
static BOOL CDecodeMsg_FinalizeSignedContent(CDecodeMsg *msg,
CRYPT_DER_BLOB *blob)
{
@@ -2377,6 +2421,9 @@ static BOOL CDecodeMsg_FinalizeContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob)
case CMSG_HASHED:
ret = CDecodeMsg_FinalizeHashedContent(msg, blob);
break;
+ case CMSG_ENVELOPED:
+ ret = CDecodeMsg_FinalizeEnvelopedContent(msg, blob);
+ break;
case CMSG_SIGNED:
ret = CDecodeMsg_FinalizeSignedContent(msg, blob);
break;
@@ -3210,6 +3257,118 @@ static BOOL CDecodeSignedMsg_VerifySignatureEx(CDecodeMsg *msg,
return ret;
}
+static BOOL WINAPI CRYPT_ImportKeyTrans(
+ PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
+ PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara, DWORD dwFlags,
+ void *pvReserved, HCRYPTKEY *phContentEncryptKey)
+{
+ BOOL ret;
+ HCRYPTKEY key;
+
+ ret = CryptGetUserKey(pKeyTransDecryptPara->hCryptProv,
+ pKeyTransDecryptPara->dwKeySpec ? pKeyTransDecryptPara->dwKeySpec :
+ AT_KEYEXCHANGE, &key);
+ if (ret)
+ {
+ CMSG_KEY_TRANS_RECIPIENT_INFO *info =
+ &pKeyTransDecryptPara->pKeyTrans[pKeyTransDecryptPara->dwRecipientIndex];
+ CRYPT_DATA_BLOB *encryptedKey = &info->EncryptedKey;
+ DWORD size = encryptedKey->cbData + sizeof(BLOBHEADER) + sizeof(ALG_ID);
+ BYTE *keyBlob = CryptMemAlloc(size);
+
+ if (keyBlob)
+ {
+ DWORD i, k = size - 1;
+ BLOBHEADER *blobHeader = (BLOBHEADER *)keyBlob;
+ ALG_ID *algID = (ALG_ID *)(keyBlob + sizeof(BLOBHEADER));
+
+ blobHeader->bType = SIMPLEBLOB;
+ blobHeader->bVersion = CUR_BLOB_VERSION;
+ blobHeader->reserved = 0;
+ blobHeader->aiKeyAlg = CertOIDToAlgId(
+ pContentEncryptionAlgorithm->pszObjId);
+ *algID = CertOIDToAlgId(info->KeyEncryptionAlgorithm.pszObjId);
+ for (i = 0; i < encryptedKey->cbData; ++i, --k)
+ keyBlob[k] = encryptedKey->pbData[i];
+
+ ret = CryptImportKey(pKeyTransDecryptPara->hCryptProv, keyBlob,
+ size, key, 0, phContentEncryptKey);
+ CryptMemFree(keyBlob);
+ }
+ else
+ ret = FALSE;
+ CryptDestroyKey(key);
+ }
+ return ret;
+}
+
+static BOOL CRYPT_ImportEncryptedKey(PCRYPT_ALGORITHM_IDENTIFIER contEncrAlg,
+ PCMSG_CTRL_DECRYPT_PARA para, PCMSG_KEY_TRANS_RECIPIENT_INFO info,
+ HCRYPTKEY *key)
+{
+ static HCRYPTOIDFUNCSET set = NULL;
+ PFN_CMSG_IMPORT_KEY_TRANS importKeyFunc = NULL;
+ HCRYPTOIDFUNCADDR hFunc = NULL;
+ CMSG_CTRL_KEY_TRANS_DECRYPT_PARA decryptPara;
+ BOOL ret;
+
+ memset(&decryptPara, 0, sizeof(decryptPara));
+ decryptPara.cbSize = sizeof(decryptPara);
+ decryptPara.hCryptProv = para->hCryptProv;
+ decryptPara.dwKeySpec = para->dwKeySpec;
+ decryptPara.pKeyTrans = info;
+ decryptPara.dwRecipientIndex = para->dwRecipientIndex;
+
+ if (!set)
+ set = CryptInitOIDFunctionSet(CMSG_OID_IMPORT_KEY_TRANS_FUNC, 0);
+ CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, contEncrAlg->pszObjId, 0,
+ (void **)&importKeyFunc, &hFunc);
+ if (!importKeyFunc)
+ importKeyFunc = CRYPT_ImportKeyTrans;
+ ret = importKeyFunc(contEncrAlg, &decryptPara, 0, NULL, key);
+ if (hFunc)
+ CryptFreeOIDFunctionAddress(hFunc, 0);
+ return ret;
+}
+
+static BOOL CDecodeEnvelopedMsg_CrtlDecrypt(CDecodeMsg *msg,
+ PCMSG_CTRL_DECRYPT_PARA para)
+{
+ BOOL ret = FALSE;
+ CEnvelopedDecodeMsg *enveloped_data = &msg->u.enveloped_data;
+ CRYPT_ENVELOPED_DATA *data = enveloped_data->data;
+
+ if (para->cbSize != sizeof(CMSG_CTRL_DECRYPT_PARA))
+ SetLastError(E_INVALIDARG);
+ else if (!data)
+ SetLastError(CRYPT_E_INVALID_MSG_TYPE);
+ else if (para->dwRecipientIndex >= data->cRecipientInfo)
+ SetLastError(CRYPT_E_INVALID_INDEX);
+ else if (enveloped_data->decrypted)
+ SetLastError(CRYPT_E_ALREADY_DECRYPTED);
+ else if (!para->hCryptProv)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (enveloped_data->content.cbData)
+ {
+ HCRYPTKEY key;
+
+ ret = CRYPT_ImportEncryptedKey(
+ &data->encryptedContentInfo.contentEncryptionAlgorithm, para,
+ data->rgRecipientInfo, &key);
+ if (ret)
+ {
+ ret = CryptDecrypt(key, 0, TRUE, 0, enveloped_data->content.pbData,
+ &enveloped_data->content.cbData);
+ CryptDestroyKey(key);
+ }
+ }
+ else
+ ret = TRUE;
+ if (ret)
+ enveloped_data->decrypted = TRUE;
+ return ret;
+}
+
static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags,
DWORD dwCtrlType, const void *pvCtrlPara)
{
@@ -3231,6 +3390,13 @@ static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags,
case CMSG_CTRL_DECRYPT:
switch (msg->type)
{
+ case CMSG_ENVELOPED:
+ ret = CDecodeEnvelopedMsg_CrtlDecrypt(msg,
+ (PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara);
+ if (ret && (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG))
+ msg->u.enveloped_data.crypt_prov =
+ ((PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara)->hCryptProv;
+ break;
default:
SetLastError(CRYPT_E_INVALID_MSG_TYPE);
}
diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c
index e32690b..20ad5c9 100644
--- a/dlls/crypt32/tests/msg.c
+++ b/dlls/crypt32/tests/msg.c
@@ -2606,7 +2606,6 @@ static void test_decode_msg_update(void)
SetLastError(0xdeadbeef);
ret = CryptMsgUpdate(msg, envelopedEmptyContent,
sizeof(envelopedEmptyContent), TRUE);
- todo_wine
ok(!ret &&
(GetLastError() == CRYPT_E_ASN1_BADTAG ||
GetLastError() == OSS_DATA_ERROR), /* Win9x */
@@ -3089,12 +3088,10 @@ static void test_decode_msg_get_param(void)
decryptPara.hCryptProv = hCryptProv;
SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
- todo_wine
ok(ret, "CryptMsgControl failed: %08x\n", GetLastError());
decryptPara.hCryptProv = 0;
SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_ALREADY_DECRYPTED,
"expected CRYPT_E_ALREADY_DECRYPTED, got %08x\n", GetLastError());
todo_wine
@@ -3118,7 +3115,6 @@ static void test_decode_msg_get_param(void)
decryptPara.hCryptProv = hCryptProv;
SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
- todo_wine
ok(ret, "CryptMsgControl failed: %08x\n", GetLastError());
todo_wine
check_param("enveloped bare message", msg, CMSG_CONTENT_PARAM, msgData,
@@ -3556,7 +3552,6 @@ static void test_msg_control(void)
decryptPara.cbSize = 0;
SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
- todo_wine
ok(!ret && GetLastError() == E_INVALIDARG,
"expected E_INVALIDARG, got %08x\n", GetLastError());
decryptPara.cbSize = sizeof(decryptPara);
@@ -3573,7 +3568,6 @@ static void test_msg_control(void)
ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
"expected CRYPT_E_INVALID_INDEX, got %08x\n", GetLastError());
CryptMsgClose(msg);
@@ -3586,7 +3580,6 @@ static void test_msg_control(void)
ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
- todo_wine
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
"expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
CryptMsgClose(msg);
commit 60be01f16d142fd88371cb3e45eca50b6d50b81f
Author: Alexander Morozov <amorozov на etersoft.ru>
Date: Wed Dec 15 16:40:01 2010 +0300
wincrypt.h: Define PFN_CMSG_IMPORT_KEY_TRANS callback function.
diff --git a/include/wincrypt.h b/include/wincrypt.h
index 7d5a87c..8834561 100644
--- a/include/wincrypt.h
+++ b/include/wincrypt.h
@@ -2281,6 +2281,7 @@ static const WCHAR CERT_TRUST_PUB_AUTHENTICODE_FLAGS_VALUE_NAME[] =
#define TIME_VALID_OID_GET_OBJECT_FUNC "TimeValidDllGetObject"
#define CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC "CryptMsgDllGenContentEncryptKey"
#define CMSG_OID_EXPORT_KEY_TRANS_FUNC "CryptMsgDllExportKeyTrans"
+#define CMSG_OID_IMPORT_KEY_TRANS_FUNC "CryptMsgDllImportKeyTrans"
#define CRYPT_OID_REGPATH "Software\\Microsoft\\Cryptography\\OID"
#define CRYPT_OID_REG_ENCODING_TYPE_PREFIX "EncodingType "
@@ -3805,6 +3806,14 @@ typedef struct _CMSG_KEY_TRANS_ENCRYPT_INFO {
DWORD dwFlags;
} CMSG_KEY_TRANS_ENCRYPT_INFO, *PCMSG_KEY_TRANS_ENCRYPT_INFO;
+typedef struct _CMSG_CTRL_KEY_TRANS_DECRYPT_PARA {
+ DWORD cbSize;
+ HCRYPTPROV hCryptProv;
+ DWORD dwKeySpec;
+ PCMSG_KEY_TRANS_RECIPIENT_INFO pKeyTrans;
+ DWORD dwRecipientIndex;
+} CMSG_CTRL_KEY_TRANS_DECRYPT_PARA, *PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA;
+
typedef BOOL (WINAPI *PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY)(
PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo, DWORD dwFlags,
void *pvReserved);
@@ -3815,6 +3824,11 @@ typedef BOOL (WINAPI *PFN_CMSG_EXPORT_KEY_TRANS)(
PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo,
DWORD dwFlags, void *pvReserved);
+typedef BOOL (WINAPI *PFN_CMSG_IMPORT_KEY_TRANS)(
+ PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
+ PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara, DWORD dwFlags,
+ void *pvReserved, HCRYPTKEY *phContentEncryptKey);
+
/* CryptMsgGetAndVerifySigner flags */
#define CMSG_TRUSTED_SIGNER_FLAG 0x1
#define CMSG_SIGNER_ONLY_FLAG 0x2
Подробная информация о списке рассылки Wine-devel