Juan Lang : crypt32: Explicitly count bytes to copy in DecodeCopyBytes.
Alexandre Julliard
julliard at winehq.org
Tue Sep 18 05:31:33 CDT 2007
Module: wine
Branch: master
Commit: 9c4c856fde5370c515714f0a81a7dc50ac647838
URL: http://source.winehq.org/git/wine.git/?a=commit;h=9c4c856fde5370c515714f0a81a7dc50ac647838
Author: Juan Lang <juan.lang at gmail.com>
Date: Mon Sep 17 17:55:13 2007 -0700
crypt32: Explicitly count bytes to copy in DecodeCopyBytes.
---
dlls/crypt32/decode.c | 127 ++++++++++++++++++++++++++++++++++---------
dlls/crypt32/tests/encode.c | 1 -
2 files changed, 101 insertions(+), 27 deletions(-)
diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c
index 8da7138..0125fef 100644
--- a/dlls/crypt32/decode.c
+++ b/dlls/crypt32/decode.c
@@ -361,10 +361,26 @@ static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
}
else
{
- ptr += itemDecoded;
- decoded += itemDecoded;
- TRACE("item %d: decoded %d bytes\n", i,
- itemDecoded);
+ if (itemLen == CMSG_INDEFINITE_LENGTH)
+ {
+ if (itemDecoded > itemEncodedLen - 2 ||
+ *(ptr + itemDecoded) != 0 ||
+ *(ptr + itemDecoded + 1) != 0)
+ {
+ TRACE("expected 0 TLV\n");
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ else
+ itemDecoded += 2;
+ }
+ if (ret)
+ {
+ ptr += itemDecoded;
+ decoded += itemDecoded;
+ TRACE("item %d: decoded %d bytes\n", i,
+ itemDecoded);
+ }
}
}
else if (items[i].optional &&
@@ -1875,41 +1891,100 @@ static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
return ret;
}
+static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE, done = FALSE;
+ DWORD indefiniteNestingLevels = 0, decoded = 0;
+
+ TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
+
+ do {
+ DWORD dataLen;
+
+ if (!cbEncoded)
+ done = TRUE;
+ else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
+ &dataLen)))
+ {
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+ if (dataLen == CMSG_INDEFINITE_LENGTH)
+ {
+ indefiniteNestingLevels++;
+ pbEncoded += 1 + lenBytes;
+ cbEncoded -= 1 + lenBytes;
+ decoded += 1 + lenBytes;
+ TRACE("indefiniteNestingLevels = %d\n",
+ indefiniteNestingLevels);
+ }
+ else
+ {
+ if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
+ indefiniteNestingLevels)
+ {
+ indefiniteNestingLevels--;
+ TRACE("indefiniteNestingLevels = %d\n",
+ indefiniteNestingLevels);
+ }
+ pbEncoded += 1 + lenBytes + dataLen;
+ cbEncoded -= 1 + lenBytes + dataLen;
+ decoded += 1 + lenBytes + dataLen;
+ if (!indefiniteNestingLevels)
+ done = TRUE;
+ }
+ }
+ } while (ret && !done);
+ /* If we haven't found all 0 TLVs, we haven't found the end */
+ if (ret && indefiniteNestingLevels)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ ret = FALSE;
+ }
+ if (ret)
+ *pcbDecoded = decoded;
+ TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
+ return ret;
+}
+
static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
DWORD *pcbDecoded)
{
BOOL ret = TRUE;
- DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
+ DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
- if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
- bytesNeeded += cbEncoded;
- if (pcbDecoded)
- *pcbDecoded = cbEncoded;
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if (*pcbStructInfo < bytesNeeded)
- {
- SetLastError(ERROR_MORE_DATA);
- *pcbStructInfo = bytesNeeded;
- ret = FALSE;
- }
- else
+ if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
{
- PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
-
- *pcbStructInfo = bytesNeeded;
- blob->cbData = cbEncoded;
- if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
- blob->pbData = (LPBYTE)pbEncoded;
+ if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
+ bytesNeeded += encodedLen;
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ *pcbStructInfo = bytesNeeded;
+ ret = FALSE;
+ }
else
{
- assert(blob->pbData);
- memcpy(blob->pbData, pbEncoded, blob->cbData);
+ PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
+
+ *pcbStructInfo = bytesNeeded;
+ blob->cbData = encodedLen;
+ if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
+ blob->pbData = (LPBYTE)pbEncoded;
+ else
+ {
+ assert(blob->pbData);
+ memcpy(blob->pbData, pbEncoded, blob->cbData);
+ }
}
+ if (pcbDecoded)
+ *pcbDecoded = encodedLen;
}
return ret;
}
diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c
index 3e29db0..eaed27b 100644
--- a/dlls/crypt32/tests/encode.c
+++ b/dlls/crypt32/tests/encode.c
@@ -4891,7 +4891,6 @@ static void test_decodePKCSContentInfo(DWORD dwEncoding)
ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
"Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
- todo_wine
ok(info->Content.cbData == 392, "Expected 392, got %d\n",
info->Content.cbData);
LocalFree(buf);
More information about the wine-cvs
mailing list