Commit b80101eb authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: Partially implement encoding signed messages.

parent 71a5859d
...@@ -82,6 +82,23 @@ typedef struct _CRYPT_DIGESTED_DATA ...@@ -82,6 +82,23 @@ typedef struct _CRYPT_DIGESTED_DATA
BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData, BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
void *pvData, DWORD *pcbData); void *pvData, DWORD *pcbData);
typedef struct _CRYPT_SIGNED_INFO
{
DWORD version;
DWORD cCertEncoded;
PCERT_BLOB rgCertEncoded;
DWORD cCrlEncoded;
PCRL_BLOB rgCrlEncoded;
DWORD cAttrCertEncoded;
PCERT_BLOB rgAttrCertEncoded;
CRYPT_CONTENT_INFO content;
DWORD cSignerInfo;
PCMSG_SIGNER_INFO rgSignerInfo;
} CRYPT_SIGNED_INFO;
BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *, void *pvData,
DWORD *pcbData);
/* Helper function to check *pcbEncoded, set it to the required size, and /* Helper function to check *pcbEncoded, set it to the required size, and
* optionally to allocate memory. Assumes pbEncoded is not NULL. * optionally to allocate memory. Assumes pbEncoded is not NULL.
* If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
......
...@@ -1540,6 +1540,88 @@ BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData, ...@@ -1540,6 +1540,88 @@ BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData); sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
} }
BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
DWORD *pcbData)
{
struct AsnEncodeSequenceItem items[7] = {
{ &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
};
CRYPT_SET_OF digestAlgorithmsSet = { 0, NULL }, signerSet = { 0, NULL };
DWORD i, cItem = 1;
BOOL ret = TRUE;
if (signedInfo->cCertEncoded)
FIXME("unimplemented for certs\n");
if (signedInfo->cCrlEncoded)
FIXME("unimplemented for CRLs\n");
if (signedInfo->cAttrCertEncoded)
FIXME("unimplemented for attr certs\n");
if (signedInfo->cSignerInfo)
{
digestAlgorithmsSet.cValue = signedInfo->cSignerInfo;
digestAlgorithmsSet.rgValue =
CryptMemAlloc(digestAlgorithmsSet.cValue * sizeof(CRYPT_DER_BLOB));
if (digestAlgorithmsSet.rgValue)
{
memset(digestAlgorithmsSet.rgValue, 0,
digestAlgorithmsSet.cValue * sizeof(CRYPT_DER_BLOB));
for (i = 0; ret && i < digestAlgorithmsSet.cValue; i++)
ret = CRYPT_AsnEncodeAlgorithmIdWithNullParams(0, NULL,
&signedInfo->rgSignerInfo[i].HashAlgorithm,
CRYPT_ENCODE_ALLOC_FLAG, NULL,
(BYTE *)&digestAlgorithmsSet.rgValue[i].pbData,
&digestAlgorithmsSet.rgValue[i].cbData);
}
else
ret = FALSE;
if (ret)
{
items[cItem].pvStructInfo = &digestAlgorithmsSet;
items[cItem].encodeFunc = CRYPT_DEREncodeSet;
cItem++;
}
}
items[cItem].pvStructInfo = &signedInfo->content;
items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
cItem++;
if (ret && signedInfo->cSignerInfo)
{
signerSet.cValue = signedInfo->cSignerInfo;
signerSet.rgValue =
CryptMemAlloc(signerSet.cValue * sizeof(CRYPT_DER_BLOB));
if (signerSet.rgValue)
{
memset(signerSet.rgValue, 0,
signerSet.cValue * sizeof(CRYPT_DER_BLOB));
for (i = 0; ret && i < signerSet.cValue; i++)
ret = CryptEncodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS7_SIGNER_INFO,
&signedInfo->rgSignerInfo[i], CRYPT_ENCODE_ALLOC_FLAG, NULL,
&signerSet.rgValue[i].pbData, &signerSet.rgValue[i].cbData);
}
else
ret = FALSE;
if (ret)
{
items[cItem].pvStructInfo = &signerSet;
items[cItem].encodeFunc = CRYPT_DEREncodeSet;
cItem++;
}
}
if (ret)
ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
pvData, pcbData);
for (i = 0; i < digestAlgorithmsSet.cValue; i++)
LocalFree(digestAlgorithmsSet.rgValue[i].pbData);
CryptMemFree(digestAlgorithmsSet.rgValue);
for (i = 0; i < signerSet.cValue; i++)
LocalFree(signerSet.rgValue[i].pbData);
CryptMemFree(signerSet.rgValue);
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
......
...@@ -627,25 +627,27 @@ static BOOL CRYPT_CopyBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in) ...@@ -627,25 +627,27 @@ static BOOL CRYPT_CopyBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in)
return ret; return ret;
} }
static BOOL CRYPT_CopyAttribute(CRYPT_ATTRIBUTE *out, const CRYPT_ATTRIBUTE *in) typedef struct _BlobArray
{
DWORD cBlobs;
PCRYPT_DATA_BLOB blobs;
} BlobArray;
static BOOL CRYPT_CopyBlobArray(BlobArray *out, const BlobArray *in)
{ {
BOOL ret = TRUE; BOOL ret = TRUE;
/* Assumption: algorithm IDs will point to static strings, not stack-based out->cBlobs = in->cBlobs;
* ones, so copying the pointer values is safe. if (out->cBlobs)
*/
out->pszObjId = in->pszObjId;
out->cValue = in->cValue;
if (out->cValue)
{ {
out->rgValue = CryptMemAlloc(out->cValue * sizeof(CRYPT_DATA_BLOB)); out->blobs = CryptMemAlloc(out->cBlobs * sizeof(CRYPT_DATA_BLOB));
if (out->rgValue) if (out->blobs)
{ {
DWORD i; DWORD i;
memset(out->rgValue, 0, out->cValue * sizeof(CRYPT_DATA_BLOB)); memset(out->blobs, 0, out->cBlobs * sizeof(CRYPT_DATA_BLOB));
for (i = 0; ret && i < out->cValue; i++) for (i = 0; ret && i < out->cBlobs; i++)
ret = CRYPT_CopyBlob(&out->rgValue[i], &in->rgValue[i]); ret = CRYPT_CopyBlob(&out->blobs[i], &in->blobs[i]);
} }
else else
ret = FALSE; ret = FALSE;
...@@ -653,6 +655,25 @@ static BOOL CRYPT_CopyAttribute(CRYPT_ATTRIBUTE *out, const CRYPT_ATTRIBUTE *in) ...@@ -653,6 +655,25 @@ static BOOL CRYPT_CopyAttribute(CRYPT_ATTRIBUTE *out, const CRYPT_ATTRIBUTE *in)
return ret; return ret;
} }
static void CRYPT_FreeBlobArray(BlobArray *array)
{
DWORD i;
for (i = 0; i < array->cBlobs; i++)
CryptMemFree(array->blobs[i].pbData);
CryptMemFree(array->blobs);
}
static BOOL CRYPT_CopyAttribute(CRYPT_ATTRIBUTE *out, const CRYPT_ATTRIBUTE *in)
{
/* Assumption: algorithm IDs will point to static strings, not stack-based
* ones, so copying the pointer values is safe.
*/
out->pszObjId = in->pszObjId;
return CRYPT_CopyBlobArray((BlobArray *)&out->cValue,
(const BlobArray *)&in->cValue);
}
static BOOL CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out, static BOOL CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out,
const CRYPT_ATTRIBUTES *in) const CRYPT_ATTRIBUTES *in)
{ {
...@@ -749,6 +770,10 @@ typedef struct _CSignedEncodeMsg ...@@ -749,6 +770,10 @@ typedef struct _CSignedEncodeMsg
CRYPT_DATA_BLOB data; CRYPT_DATA_BLOB data;
DWORD cSigners; DWORD cSigners;
CSignerInfo *signers; CSignerInfo *signers;
DWORD cCertEncoded;
PCERT_BLOB rgCertEncoded;
DWORD cCrlEncoded;
PCRL_BLOB rgCrlEncoded;
} CSignedEncodeMsg; } CSignedEncodeMsg;
static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg) static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg)
...@@ -757,6 +782,8 @@ static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg) ...@@ -757,6 +782,8 @@ static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg)
DWORD i; DWORD i;
CryptMemFree(msg->data.pbData); CryptMemFree(msg->data.pbData);
CRYPT_FreeBlobArray((BlobArray *)&msg->cCertEncoded);
CRYPT_FreeBlobArray((BlobArray *)&msg->cCrlEncoded);
for (i = 0; i < msg->cSigners; i++) for (i = 0; i < msg->cSigners; i++)
CSignerInfo_Free(&msg->signers[i]); CSignerInfo_Free(&msg->signers[i]);
CryptMemFree(msg->signers); CryptMemFree(msg->signers);
...@@ -770,6 +797,55 @@ static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, ...@@ -770,6 +797,55 @@ static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
switch (dwParamType) switch (dwParamType)
{ {
case CMSG_BARE_CONTENT_PARAM:
{
CRYPT_SIGNED_INFO info;
char oid_rsa_data[] = szOID_RSA_data;
/* Note: needs to change if CMS fields are supported */
info.version = CMSG_SIGNED_DATA_V1;
info.cCertEncoded = msg->cCertEncoded;
info.rgCertEncoded = msg->rgCertEncoded;
info.cCrlEncoded = msg->cCrlEncoded;
info.rgCrlEncoded = msg->rgCrlEncoded;
info.cAttrCertEncoded = 0;
info.cSignerInfo = msg->cSigners;
/* Quirk: OID is only encoded messages if an update has happened */
if (msg->base.state != MsgStateInit)
info.content.pszObjId = oid_rsa_data;
else
info.content.pszObjId = NULL;
if (msg->data.cbData)
{
CRYPT_DATA_BLOB blob = { msg->data.cbData, msg->data.pbData };
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
&blob, CRYPT_ENCODE_ALLOC_FLAG, NULL,
&info.content.Content.pbData, &info.content.Content.cbData);
}
else
{
info.content.Content.cbData = 0;
info.content.Content.pbData = NULL;
ret = TRUE;
}
if (ret)
{
info.rgSignerInfo =
CryptMemAlloc(msg->cSigners * sizeof(CMSG_SIGNER_INFO));
if (info.rgSignerInfo)
{
DWORD i;
for (i = 0; i < info.cSignerInfo; i++)
info.rgSignerInfo[i] = msg->signers[i].info;
ret = CRYPT_AsnEncodePKCSSignedInfo(&info, pvData, pcbData);
CryptMemFree(info.rgSignerInfo);
}
LocalFree(info.content.Content.pbData);
}
break;
}
case CMSG_COMPUTED_HASH_PARAM: case CMSG_COMPUTED_HASH_PARAM:
if (dwIndex >= msg->cSigners) if (dwIndex >= msg->cSigners)
SetLastError(CRYPT_E_INVALID_INDEX); SetLastError(CRYPT_E_INVALID_INDEX);
...@@ -931,6 +1007,12 @@ static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags, ...@@ -931,6 +1007,12 @@ static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags,
else else
ret = FALSE; ret = FALSE;
} }
if (ret)
ret = CRYPT_CopyBlobArray((BlobArray *)&msg->cCertEncoded,
(const BlobArray *)&info->cCertEncoded);
if (ret)
ret = CRYPT_CopyBlobArray((BlobArray *)&msg->cCrlEncoded,
(const BlobArray *)&info->cCrlEncoded);
if (!ret) if (!ret)
{ {
CSignedEncodeMsg_Close(msg); CSignedEncodeMsg_Close(msg);
......
...@@ -1289,7 +1289,6 @@ static void test_signed_msg_encoding(void) ...@@ -1289,7 +1289,6 @@ static void test_signed_msg_encoding(void)
CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL); CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError()); ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
todo_wine
check_param("detached signed empty bare content", msg, check_param("detached signed empty bare content", msg,
CMSG_BARE_CONTENT_PARAM, signedEmptyBareContent, CMSG_BARE_CONTENT_PARAM, signedEmptyBareContent,
sizeof(signedEmptyBareContent)); sizeof(signedEmptyBareContent));
...@@ -1300,7 +1299,6 @@ static void test_signed_msg_encoding(void) ...@@ -1300,7 +1299,6 @@ static void test_signed_msg_encoding(void)
ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError()); ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
check_param("detached signed hash", msg, CMSG_COMPUTED_HASH_PARAM, check_param("detached signed hash", msg, CMSG_COMPUTED_HASH_PARAM,
signedHash, sizeof(signedHash)); signedHash, sizeof(signedHash));
todo_wine
check_param("detached signed bare content", msg, CMSG_BARE_CONTENT_PARAM, check_param("detached signed bare content", msg, CMSG_BARE_CONTENT_PARAM,
detachedSignedBareContent, sizeof(detachedSignedBareContent)); detachedSignedBareContent, sizeof(detachedSignedBareContent));
todo_wine todo_wine
...@@ -1317,7 +1315,6 @@ static void test_signed_msg_encoding(void) ...@@ -1317,7 +1315,6 @@ static void test_signed_msg_encoding(void)
NULL, NULL); NULL, NULL);
ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError()); ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
todo_wine
check_param("signed empty bare content", msg, CMSG_BARE_CONTENT_PARAM, check_param("signed empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
signedEmptyBareContent, sizeof(signedEmptyBareContent)); signedEmptyBareContent, sizeof(signedEmptyBareContent));
todo_wine todo_wine
...@@ -1325,7 +1322,6 @@ static void test_signed_msg_encoding(void) ...@@ -1325,7 +1322,6 @@ static void test_signed_msg_encoding(void)
signedEmptyContent, sizeof(signedEmptyContent)); signedEmptyContent, sizeof(signedEmptyContent));
ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError()); ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
todo_wine
check_param("signed bare content", msg, CMSG_BARE_CONTENT_PARAM, check_param("signed bare content", msg, CMSG_BARE_CONTENT_PARAM,
signedBareContent, sizeof(signedBareContent)); signedBareContent, sizeof(signedBareContent));
todo_wine todo_wine
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment