From cb97a1738a3a2b522c36f458696794be1d91c919 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Mon, 17 Sep 2007 17:55:13 -0700 Subject: [PATCH] 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 } 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_AsnDecodeUnicod 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(D 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); -- 1.4.1