Commit 2d359268 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: Separate signer handles from signer info to avoid unnecessary memory allocation.

parent 937b27f3
...@@ -601,13 +601,12 @@ static BOOL CRYPT_IsValidSigner(CMSG_SIGNER_ENCODE_INFO_WITH_CMS *signer) ...@@ -601,13 +601,12 @@ static BOOL CRYPT_IsValidSigner(CMSG_SIGNER_ENCODE_INFO_WITH_CMS *signer)
return TRUE; return TRUE;
} }
typedef struct _CSignerInfo typedef struct _CSignerHandles
{ {
HCRYPTPROV prov; HCRYPTPROV prov;
HCRYPTHASH hash; HCRYPTHASH hash;
HCRYPTKEY key; HCRYPTKEY key;
CMSG_SIGNER_INFO info; } CSignerHandles;
} CSignerInfo;
static BOOL CRYPT_CopyBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in) static BOOL CRYPT_CopyBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in)
{ {
...@@ -699,81 +698,82 @@ static BOOL CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out, ...@@ -699,81 +698,82 @@ static BOOL CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out,
return ret; return ret;
} }
static BOOL CSignerInfo_Construct(CSignerInfo *out, /* Constructs both a CSignerHandles and a CMSG_SIGNER_INFO from a
CMSG_SIGNER_ENCODE_INFO_WITH_CMS *in, DWORD open_flags) * CMSG_SIGNER_ENCODE_INFO_WITH_CMS.
*/
static BOOL CSignerInfo_Construct(CSignerHandles *handles,
CMSG_SIGNER_INFO *info, CMSG_SIGNER_ENCODE_INFO_WITH_CMS *in, DWORD open_flags)
{ {
ALG_ID algID; ALG_ID algID;
BOOL ret; BOOL ret;
out->prov = in->hCryptProv; handles->prov = in->hCryptProv;
if (!(open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)) if (!(open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG))
CryptContextAddRef(out->prov, NULL, 0); CryptContextAddRef(handles->prov, NULL, 0);
algID = CertOIDToAlgId(in->HashAlgorithm.pszObjId); algID = CertOIDToAlgId(in->HashAlgorithm.pszObjId);
ret = CryptCreateHash(out->prov, algID, 0, 0, &out->hash); ret = CryptCreateHash(handles->prov, algID, 0, 0, &handles->hash);
if (ret) if (ret)
{ {
/* Note: needs to change if CMS fields are supported */ /* Note: needs to change if CMS fields are supported */
out->info.dwVersion = CMSG_SIGNER_INFO_V1; info->dwVersion = CMSG_SIGNER_INFO_V1;
ret = CRYPT_CopyBlob(&out->info.Issuer, &in->pCertInfo->Issuer); ret = CRYPT_CopyBlob(&info->Issuer, &in->pCertInfo->Issuer);
if (ret) if (ret)
ret = CRYPT_CopyBlob(&out->info.SerialNumber, ret = CRYPT_CopyBlob(&info->SerialNumber,
&in->pCertInfo->SerialNumber); &in->pCertInfo->SerialNumber);
/* Assumption: algorithm IDs will point to static strings, not /* Assumption: algorithm IDs will point to static strings, not
* stack-based ones, so copying the pointer values is safe. * stack-based ones, so copying the pointer values is safe.
*/ */
out->info.HashAlgorithm.pszObjId = in->HashAlgorithm.pszObjId; info->HashAlgorithm.pszObjId = in->HashAlgorithm.pszObjId;
if (ret) if (ret)
ret = CRYPT_CopyBlob(&out->info.HashAlgorithm.Parameters, ret = CRYPT_CopyBlob(&info->HashAlgorithm.Parameters,
&in->HashAlgorithm.Parameters); &in->HashAlgorithm.Parameters);
memset(&out->info.HashEncryptionAlgorithm, 0, memset(&info->HashEncryptionAlgorithm, 0,
sizeof(out->info.HashEncryptionAlgorithm)); sizeof(info->HashEncryptionAlgorithm));
if (ret) if (ret)
ret = CRYPT_CopyAttributes(&out->info.AuthAttrs, ret = CRYPT_CopyAttributes(&info->AuthAttrs,
(CRYPT_ATTRIBUTES *)&in->cAuthAttr); (CRYPT_ATTRIBUTES *)&in->cAuthAttr);
if (ret) if (ret)
ret = CRYPT_CopyAttributes(&out->info.UnauthAttrs, ret = CRYPT_CopyAttributes(&info->UnauthAttrs,
(CRYPT_ATTRIBUTES *)&in->cUnauthAttr); (CRYPT_ATTRIBUTES *)&in->cUnauthAttr);
} }
return ret; return ret;
} }
static void CSignerInfo_Free(CSignerInfo *signer) static void CSignerInfo_Free(CMSG_SIGNER_INFO *info)
{ {
DWORD i, j; DWORD i, j;
CryptDestroyKey(signer->key); CryptMemFree(info->Issuer.pbData);
CryptDestroyHash(signer->hash); CryptMemFree(info->SerialNumber.pbData);
CryptReleaseContext(signer->prov, 0); CryptMemFree(info->HashAlgorithm.Parameters.pbData);
CryptMemFree(signer->info.Issuer.pbData); CryptMemFree(info->EncryptedHash.pbData);
CryptMemFree(signer->info.SerialNumber.pbData); for (i = 0; i < info->AuthAttrs.cAttr; i++)
CryptMemFree(signer->info.HashAlgorithm.Parameters.pbData);
CryptMemFree(signer->info.EncryptedHash.pbData);
for (i = 0; i < signer->info.AuthAttrs.cAttr; i++)
{ {
for (j = 0; j < signer->info.AuthAttrs.rgAttr[i].cValue; j++) for (j = 0; j < info->AuthAttrs.rgAttr[i].cValue; j++)
CryptMemFree(signer->info.AuthAttrs.rgAttr[i].rgValue[j].pbData); CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue[j].pbData);
CryptMemFree(signer->info.AuthAttrs.rgAttr[i].rgValue); CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue);
} }
CryptMemFree(signer->info.AuthAttrs.rgAttr); CryptMemFree(info->AuthAttrs.rgAttr);
for (i = 0; i < signer->info.UnauthAttrs.cAttr; i++) for (i = 0; i < info->UnauthAttrs.cAttr; i++)
{ {
for (j = 0; j < signer->info.UnauthAttrs.rgAttr[i].cValue; j++) for (j = 0; j < info->UnauthAttrs.rgAttr[i].cValue; j++)
CryptMemFree(signer->info.UnauthAttrs.rgAttr[i].rgValue[j].pbData); CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue[j].pbData);
CryptMemFree(signer->info.UnauthAttrs.rgAttr[i].rgValue); CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue);
} }
CryptMemFree(signer->info.UnauthAttrs.rgAttr); CryptMemFree(info->UnauthAttrs.rgAttr);
} }
typedef struct _CSignedEncodeMsg typedef struct _CSignedEncodeMsg
{ {
CryptMsgBase base; CryptMsgBase base;
CRYPT_DATA_BLOB data; CRYPT_DATA_BLOB data;
DWORD cSigners; DWORD cSigners;
CSignerInfo *signers; CSignerHandles *signerHandles;
DWORD cCertEncoded; PCMSG_SIGNER_INFO rgSignerInfo;
PCERT_BLOB rgCertEncoded; DWORD cCertEncoded;
DWORD cCrlEncoded; PCERT_BLOB rgCertEncoded;
PCRL_BLOB rgCrlEncoded; DWORD cCrlEncoded;
PCRL_BLOB rgCrlEncoded;
} CSignedEncodeMsg; } CSignedEncodeMsg;
static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg) static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg)
...@@ -785,8 +785,14 @@ static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg) ...@@ -785,8 +785,14 @@ static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg)
CRYPT_FreeBlobArray((BlobArray *)&msg->cCertEncoded); CRYPT_FreeBlobArray((BlobArray *)&msg->cCertEncoded);
CRYPT_FreeBlobArray((BlobArray *)&msg->cCrlEncoded); CRYPT_FreeBlobArray((BlobArray *)&msg->cCrlEncoded);
for (i = 0; i < msg->cSigners; i++) for (i = 0; i < msg->cSigners; i++)
CSignerInfo_Free(&msg->signers[i]); {
CryptMemFree(msg->signers); CSignerInfo_Free(&msg->rgSignerInfo[i]);
CryptDestroyKey(msg->signerHandles[i].key);
CryptDestroyHash(msg->signerHandles[i].hash);
CryptReleaseContext(msg->signerHandles[i].prov, 0);
}
CryptMemFree(msg->signerHandles);
CryptMemFree(msg->rgSignerInfo);
} }
static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
...@@ -859,17 +865,8 @@ static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, ...@@ -859,17 +865,8 @@ static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
} }
if (ret) if (ret)
{ {
info.rgSignerInfo = info.rgSignerInfo = msg->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); ret = CRYPT_AsnEncodePKCSSignedInfo(&info, pvData, pcbData);
CryptMemFree(info.rgSignerInfo);
}
LocalFree(info.content.Content.pbData); LocalFree(info.content.Content.pbData);
} }
break; break;
...@@ -878,8 +875,8 @@ static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, ...@@ -878,8 +875,8 @@ static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
if (dwIndex >= msg->cSigners) if (dwIndex >= msg->cSigners)
SetLastError(CRYPT_E_INVALID_INDEX); SetLastError(CRYPT_E_INVALID_INDEX);
else else
ret = CryptGetHashParam(msg->signers[dwIndex].hash, HP_HASHVAL, ret = CryptGetHashParam(msg->signerHandles[dwIndex].hash,
pvData, pcbData, 0); HP_HASHVAL, pvData, pcbData, 0);
break; break;
default: default:
FIXME("unimplemented for %d\n", dwParamType); FIXME("unimplemented for %d\n", dwParamType);
...@@ -897,7 +894,7 @@ static BOOL CSignedEncodeMsg_UpdateHash(CSignedEncodeMsg *msg, ...@@ -897,7 +894,7 @@ static BOOL CSignedEncodeMsg_UpdateHash(CSignedEncodeMsg *msg,
TRACE("(%p, %p, %d)\n", msg, pbData, cbData); TRACE("(%p, %p, %d)\n", msg, pbData, cbData);
for (i = 0; ret && i < msg->cSigners; i++) for (i = 0; ret && i < msg->cSigners; i++)
ret = CryptHashData(msg->signers[i].hash, pbData, cbData, 0); ret = CryptHashData(msg->signerHandles[i].hash, pbData, cbData, 0);
return ret; return ret;
} }
...@@ -923,19 +920,19 @@ static BOOL CSignedEncodeMsg_Sign(CSignedEncodeMsg *msg) ...@@ -923,19 +920,19 @@ static BOOL CSignedEncodeMsg_Sign(CSignedEncodeMsg *msg)
for (i = 0; ret && i < msg->cSigners; i++) for (i = 0; ret && i < msg->cSigners; i++)
{ {
ret = CryptSignHashW(msg->signers[i].hash, AT_SIGNATURE, NULL, 0, NULL, ret = CryptSignHashW(msg->signerHandles[i].hash, AT_SIGNATURE, NULL, 0,
&msg->signers[i].info.EncryptedHash.cbData); NULL, &msg->rgSignerInfo[i].EncryptedHash.cbData);
if (ret) if (ret)
{ {
msg->signers[i].info.EncryptedHash.pbData = msg->rgSignerInfo[i].EncryptedHash.pbData =
CryptMemAlloc(msg->signers[i].info.EncryptedHash.cbData); CryptMemAlloc(msg->rgSignerInfo[i].EncryptedHash.cbData);
if (msg->signers[i].info.EncryptedHash.pbData) if (msg->rgSignerInfo[i].EncryptedHash.pbData)
{ {
ret = CryptSignHashW(msg->signers[i].hash, AT_SIGNATURE, NULL, ret = CryptSignHashW(msg->signerHandles[i].hash, AT_SIGNATURE,
0, msg->signers[i].info.EncryptedHash.pbData, NULL, 0, msg->rgSignerInfo[i].EncryptedHash.pbData,
&msg->signers[i].info.EncryptedHash.cbData); &msg->rgSignerInfo[i].EncryptedHash.cbData);
if (ret) if (ret)
CRYPT_ReverseBytes(&msg->signers[i].info.EncryptedHash); CRYPT_ReverseBytes(&msg->rgSignerInfo[i].EncryptedHash);
} }
else else
ret = FALSE; ret = FALSE;
...@@ -1023,14 +1020,26 @@ static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags, ...@@ -1023,14 +1020,26 @@ static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags,
msg->cSigners = 0; msg->cSigners = 0;
if (info->cSigners) if (info->cSigners)
{ {
msg->signers = CryptMemAlloc(info->cSigners * sizeof(CSignerInfo)); msg->signerHandles =
if (msg->signers) CryptMemAlloc(info->cSigners * sizeof(CSignerHandles));
if (msg->signerHandles)
msg->rgSignerInfo =
CryptMemAlloc(info->cSigners * sizeof(CMSG_SIGNER_INFO));
else
{
ret = FALSE;
msg->rgSignerInfo = NULL;
}
if (msg->rgSignerInfo)
{ {
msg->cSigners = info->cSigners; msg->cSigners = info->cSigners;
memset(msg->signers, 0, msg->cSigners * sizeof(CSignerInfo)); memset(msg->signerHandles, 0,
msg->cSigners * sizeof(CSignerHandles));
memset(msg->rgSignerInfo, 0,
msg->cSigners * sizeof(CMSG_SIGNER_INFO));
for (i = 0; ret && i < msg->cSigners; i++) for (i = 0; ret && i < msg->cSigners; i++)
ret = CSignerInfo_Construct(&msg->signers[i], ret = CSignerInfo_Construct(&msg->signerHandles[i],
&info->rgSigners[i], dwFlags); &msg->rgSignerInfo[i], &info->rgSigners[i], dwFlags);
} }
else else
ret = FALSE; ret = FALSE;
......
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