mirror of
https://github.com/reactos/wine.git
synced 2024-11-29 06:30:37 +00:00
Correct a bunch of lurking asn.1 decode bugs.
This commit is contained in:
parent
932ecb24eb
commit
a5082b2544
@ -141,7 +141,8 @@ static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
|
||||
static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
|
||||
static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
|
||||
/* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
|
||||
static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
|
||||
/* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
|
||||
@ -956,7 +957,6 @@ static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
|
||||
{ &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
struct AsnConstructedItem constructed = { 0 };
|
||||
DWORD cItem = 4;
|
||||
|
||||
if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
|
||||
@ -973,13 +973,8 @@ static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
|
||||
}
|
||||
if (info->cExtension)
|
||||
{
|
||||
/* FIXME: is this really constructed? if so, is this the right tag?
|
||||
*/
|
||||
constructed.tag = 3;
|
||||
constructed.pvStructInfo = &info->cExtension;
|
||||
constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
|
||||
items[cItem].pvStructInfo = &constructed;
|
||||
items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
|
||||
items[cItem].pvStructInfo = &info->cExtension;
|
||||
items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
|
||||
cItem++;
|
||||
}
|
||||
|
||||
@ -1571,6 +1566,7 @@ static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
|
||||
*pcbEncoded = bytesNeeded;
|
||||
}
|
||||
}
|
||||
TRACE("returning %d (%08lx)\n", ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1599,6 +1595,15 @@ static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
|
||||
&len);
|
||||
if (ret)
|
||||
dataLen += len;
|
||||
else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
|
||||
{
|
||||
/* CRYPT_AsnEncodeAltNameEntry encoded the index of
|
||||
* the bad character, now set the index of the bad
|
||||
* entry
|
||||
*/
|
||||
*pcbEncoded = (BYTE)i <<
|
||||
CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
@ -1630,15 +1635,6 @@ static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
|
||||
pbEncoded += len;
|
||||
dataLen -= len;
|
||||
}
|
||||
else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
|
||||
{
|
||||
/* CRYPT_AsnEncodeAltNameEntry encoded the index of
|
||||
* the bad character, now set the index of the bad
|
||||
* entry
|
||||
*/
|
||||
*pcbEncoded |= (BYTE)i <<
|
||||
CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2538,6 +2534,10 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
|
||||
* decoded, but minSize space is reserved for it.
|
||||
* minSize:
|
||||
* The minimum amount of space occupied after decoding. You must set this.
|
||||
* optional:
|
||||
* If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
|
||||
* minSize space is filled with 0 for this member. (Any other failure
|
||||
* results in CRYPT_AsnDecodeSequence failing.)
|
||||
* hasPointer, pointerOffset, minSize:
|
||||
* If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
|
||||
* the offset within the (outer) struct of the data pointer (or to the
|
||||
@ -2564,7 +2564,6 @@ struct AsnDecodeSequenceItem
|
||||
* here. Otherwise, pass NULL, and one will be inferred from the items.
|
||||
* Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
|
||||
* If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
|
||||
* FIXME: use to decode more sequences.
|
||||
*/
|
||||
static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
|
||||
struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
|
||||
@ -2573,8 +2572,9 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld\n", items, cItem, pbEncoded,
|
||||
cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
|
||||
TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
|
||||
cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
|
||||
startingPointer);
|
||||
|
||||
if (pbEncoded[0] == ASN_SEQUENCE)
|
||||
{
|
||||
@ -2601,6 +2601,7 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
|
||||
|
||||
if (items[i].decodeFunc)
|
||||
{
|
||||
TRACE("sizing item %ld\n", i);
|
||||
ret = items[i].decodeFunc(dwCertEncodingType, NULL,
|
||||
ptr, 1 + nextItemLenBytes + nextItemLen,
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
|
||||
@ -2617,10 +2618,14 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
|
||||
else if (items[i].optional &&
|
||||
GetLastError() == CRYPT_E_ASN1_BADTAG)
|
||||
{
|
||||
TRACE("skipping optional item %ld\n", i);
|
||||
bytesNeeded += items[i].minSize;
|
||||
SetLastError(NOERROR);
|
||||
ret = TRUE;
|
||||
}
|
||||
else
|
||||
TRACE("item %ld failed: %08lx\n", i,
|
||||
GetLastError());
|
||||
}
|
||||
else
|
||||
bytesNeeded += items[i].minSize;
|
||||
@ -2634,6 +2639,13 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
if (cbEncoded - (ptr - pbEncoded) != 0)
|
||||
{
|
||||
TRACE("%ld remaining bytes, failing\n", cbEncoded -
|
||||
(ptr - pbEncoded));
|
||||
SetLastError(CRYPT_E_ASN1_CORRUPT);
|
||||
ret = FALSE;
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
if (!pvStructInfo)
|
||||
@ -2661,14 +2673,22 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
|
||||
CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
|
||||
&nextItemLen);
|
||||
if (items[i].hasPointer)
|
||||
{
|
||||
*(BYTE **)((BYTE *)pvStructInfo +
|
||||
items[i].pointerOffset) = nextData;
|
||||
}
|
||||
if (items[i].decodeFunc)
|
||||
{
|
||||
TRACE("decoding item %ld\n", i);
|
||||
ret = items[i].decodeFunc(dwCertEncodingType,
|
||||
NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
(BYTE *)pvStructInfo + items[i].offset,
|
||||
&items[i].size);
|
||||
if (!ret)
|
||||
TRACE("item %ld failed: %08lx\n", i,
|
||||
GetLastError());
|
||||
}
|
||||
else
|
||||
items[i].size = items[i].minSize;
|
||||
if (ret)
|
||||
@ -2680,8 +2700,10 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
|
||||
items[i].minSize;
|
||||
/* align nextData to DWORD boundaries */
|
||||
if (items[i].size % sizeof(DWORD))
|
||||
{
|
||||
nextData += sizeof(DWORD) -
|
||||
items[i].size % sizeof(DWORD);
|
||||
}
|
||||
}
|
||||
ptr += 1 + nextItemLenBytes + nextItemLen;
|
||||
}
|
||||
@ -2767,21 +2789,33 @@ static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, *pcbStructInfo);
|
||||
|
||||
/* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
|
||||
* place.
|
||||
*/
|
||||
ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
|
||||
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
|
||||
pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
|
||||
pvStructInfo, pcbStructInfo);
|
||||
if (ret && pvStructInfo)
|
||||
{
|
||||
CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
|
||||
DWORD i;
|
||||
BYTE temp;
|
||||
|
||||
for (i = 0; i < blob->cbData / 2; i++)
|
||||
if (blob->cbData)
|
||||
{
|
||||
temp = blob->pbData[i];
|
||||
blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
|
||||
blob->pbData[blob->cbData - i - 1] = temp;
|
||||
DWORD i;
|
||||
BYTE temp;
|
||||
|
||||
for (i = 0; i < blob->cbData / 2; i++)
|
||||
{
|
||||
temp = blob->pbData[i];
|
||||
blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
|
||||
blob->pbData[blob->cbData - i - 1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
TRACE("returning %d (%08lx)\n", ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2803,7 +2837,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
|
||||
{ offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm),
|
||||
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
|
||||
FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO,
|
||||
SignatureAlgorithm.Parameters.pbData), 0 },
|
||||
SignatureAlgorithm.pszObjId), 0 },
|
||||
{ offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
|
||||
CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
|
||||
offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
|
||||
@ -2870,6 +2904,33 @@ static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 3))
|
||||
{
|
||||
DWORD dataLen;
|
||||
|
||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
{
|
||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
||||
|
||||
ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
|
||||
X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
|
||||
pDecodePara, pvStructInfo, pcbStructInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
@ -2889,7 +2950,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
|
||||
SerialNumber.pbData), 0 },
|
||||
{ offsetof(CERT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
|
||||
sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_INFO,
|
||||
SignatureAlgorithm.Parameters.pbData), 0 },
|
||||
SignatureAlgorithm.pszObjId), 0 },
|
||||
{ offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
|
||||
sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
|
||||
Issuer.pbData) },
|
||||
@ -2907,7 +2968,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
|
||||
{ offsetof(CERT_INFO, SubjectUniqueId), CRYPT_AsnDecodeBitsInternal,
|
||||
sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
|
||||
SubjectUniqueId.pbData), 0 },
|
||||
{ offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeExtensionsInternal,
|
||||
{ offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeCertExtensions,
|
||||
sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CERT_INFO,
|
||||
rgExtension), 0 },
|
||||
};
|
||||
@ -3075,7 +3136,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
|
||||
sizeof(DWORD), TRUE, FALSE, 0, 0 },
|
||||
{ offsetof(CRL_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
|
||||
sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRL_INFO,
|
||||
SignatureAlgorithm.Parameters.pbData), 0 },
|
||||
SignatureAlgorithm.pszObjId), 0 },
|
||||
{ offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
|
||||
sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
|
||||
Issuer.pbData) },
|
||||
@ -3107,97 +3168,57 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Warning: assumes ext->Value.pbData is set ahead of time! */
|
||||
/* Differences between this and CRYPT_AsnDecodeOid:
|
||||
* - pvStructInfo is a LPSTR *, not an LPSTR
|
||||
* - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
|
||||
* count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
|
||||
* to
|
||||
*/
|
||||
static BOOL WINAPI CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, *pcbStructInfo);
|
||||
|
||||
ret = CRYPT_AsnDecodeOid(pbEncoded, cbEncoded, dwFlags,
|
||||
pvStructInfo ? *(LPSTR *)pvStructInfo : NULL, pcbStructInfo);
|
||||
if (ret || GetLastError() == ERROR_MORE_DATA)
|
||||
*pcbStructInfo += sizeof(LPSTR);
|
||||
if (ret && pvStructInfo)
|
||||
TRACE("returning %s\n", debugstr_a(*(LPSTR *)pvStructInfo));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Warning: assumes ext->pszObjId is set ahead of time! */
|
||||
static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
|
||||
DWORD dwFlags, CERT_EXTENSION *ext, DWORD *pcbExt)
|
||||
{
|
||||
struct AsnDecodeSequenceItem items[] = {
|
||||
{ offsetof(CERT_EXTENSION, pszObjId), CRYPT_AsnDecodeOidWrapper,
|
||||
sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_EXTENSION, pszObjId), 0 },
|
||||
{ offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
|
||||
sizeof(BOOL), TRUE, FALSE, 0, 0 },
|
||||
{ offsetof(CERT_EXTENSION, Value), CRYPT_AsnDecodeOctetsInternal,
|
||||
sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, offsetof(CERT_EXTENSION,
|
||||
Value.pbData) },
|
||||
};
|
||||
BOOL ret = TRUE;
|
||||
|
||||
if (pbEncoded[0] == ASN_SEQUENCE)
|
||||
{
|
||||
DWORD dataLen, bytesNeeded;
|
||||
TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
|
||||
*pcbExt);
|
||||
|
||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
{
|
||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]), oidLenBytes = 0;
|
||||
|
||||
bytesNeeded = sizeof(CERT_EXTENSION);
|
||||
if (dataLen)
|
||||
{
|
||||
const BYTE *ptr = pbEncoded + 1 + lenBytes;
|
||||
DWORD encodedOidLen, oidLen;
|
||||
|
||||
CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
|
||||
&encodedOidLen);
|
||||
oidLenBytes = GET_LEN_BYTES(ptr[1]);
|
||||
ret = CRYPT_AsnDecodeOid(ptr, cbEncoded - (ptr - pbEncoded),
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &oidLen);
|
||||
if (ret)
|
||||
{
|
||||
bytesNeeded += oidLen;
|
||||
ptr += 1 + encodedOidLen + oidLenBytes;
|
||||
if (*ptr == ASN_BOOL)
|
||||
ptr += 3;
|
||||
ret = CRYPT_AsnDecodeOctets(X509_ASN_ENCODING,
|
||||
X509_OCTET_STRING, ptr, cbEncoded - (ptr - pbEncoded),
|
||||
0, NULL, NULL, &dataLen);
|
||||
bytesNeeded += dataLen;
|
||||
if (ret)
|
||||
{
|
||||
if (!ext)
|
||||
*pcbExt = bytesNeeded;
|
||||
else if (*pcbExt < bytesNeeded)
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = pbEncoded + 2 + lenBytes + encodedOidLen +
|
||||
oidLenBytes;
|
||||
if (*ptr == ASN_BOOL)
|
||||
{
|
||||
DWORD size = sizeof(BOOL);
|
||||
|
||||
CRYPT_AsnDecodeBool(X509_ASN_ENCODING, NULL,
|
||||
ptr, cbEncoded - (ptr - pbEncoded),
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
&ext->fCritical, &size);
|
||||
ptr += 3;
|
||||
}
|
||||
else
|
||||
ext->fCritical = FALSE;
|
||||
ret = CRYPT_AsnDecodeOctets(X509_ASN_ENCODING,
|
||||
X509_OCTET_STRING, ptr,
|
||||
cbEncoded - (ptr - pbEncoded),
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
&ext->Value, &dataLen);
|
||||
if (ret)
|
||||
{
|
||||
ext->pszObjId = (LPSTR)ext->Value.pbData +
|
||||
ext->Value.cbData;
|
||||
ptr = pbEncoded + 1 + lenBytes;
|
||||
ret = CRYPT_AsnDecodeOid(ptr,
|
||||
cbEncoded - (ptr - pbEncoded),
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
|
||||
ext->pszObjId, &oidLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_EOD);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
if (ext)
|
||||
TRACE("ext->pszObjId is %p\n", ext->pszObjId);
|
||||
ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
|
||||
sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
|
||||
ext, pcbExt, ext ? ext->pszObjId : NULL);
|
||||
if (ext)
|
||||
TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
|
||||
debugstr_a(ext->pszObjId));
|
||||
TRACE("returning %d (%08lx)\n", ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3207,6 +3228,9 @@ static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
|
||||
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, *pcbStructInfo);
|
||||
|
||||
if (pbEncoded[0] == ASN_SEQUENCEOF)
|
||||
{
|
||||
DWORD dataLen, bytesNeeded;
|
||||
@ -3225,6 +3249,7 @@ static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
|
||||
for (ptr = pbEncoded + 1 + lenBytes; ret &&
|
||||
ptr - pbEncoded - 1 - lenBytes < dataLen; )
|
||||
{
|
||||
size = 0;
|
||||
ret = CRYPT_AsnDecodeExtension(ptr,
|
||||
cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
|
||||
if (ret)
|
||||
@ -3267,7 +3292,7 @@ static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
|
||||
i < cExtension && ptr - pbEncoded - 1 - lenBytes <
|
||||
dataLen; i++)
|
||||
{
|
||||
exts->rgExtension[i].Value.pbData = nextData;
|
||||
exts->rgExtension[i].pszObjId = nextData;
|
||||
size = bytesNeeded;
|
||||
ret = CRYPT_AsnDecodeExtension(ptr,
|
||||
cbEncoded - (ptr - pbEncoded), dwFlags,
|
||||
@ -3277,21 +3302,8 @@ static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
|
||||
DWORD nextLen;
|
||||
|
||||
bytesNeeded -= size;
|
||||
/* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
|
||||
* data may not have been copied.
|
||||
*/
|
||||
if (exts->rgExtension[i].Value.pbData ==
|
||||
nextData)
|
||||
nextData +=
|
||||
exts->rgExtension[i].Value.cbData;
|
||||
/* Ugly: the OID, if copied, is stored in
|
||||
* memory after the value, so increment by its
|
||||
* string length if it's set and points here.
|
||||
*/
|
||||
if ((const BYTE *)exts->rgExtension[i].pszObjId
|
||||
== nextData)
|
||||
nextData += strlen(
|
||||
exts->rgExtension[i].pszObjId) + 1;
|
||||
if (size > sizeof(CERT_EXTENSION))
|
||||
nextData += size - sizeof(CERT_EXTENSION);
|
||||
ret = CRYPT_GetLen(ptr,
|
||||
cbEncoded - (ptr - pbEncoded), &nextLen);
|
||||
if (ret)
|
||||
@ -3356,6 +3368,9 @@ static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
|
||||
TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, pszObjId,
|
||||
*pcbObjId);
|
||||
|
||||
__TRY
|
||||
{
|
||||
if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
|
||||
@ -3418,6 +3433,7 @@ static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
|
||||
}
|
||||
else
|
||||
{
|
||||
*pszObjId = 0;
|
||||
sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
|
||||
pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
|
||||
40) * 40);
|
||||
@ -3563,6 +3579,9 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValue(const BYTE *pbEncoded,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it
|
||||
* at the moment because of the ASN_CONSTRUCTOR tag.)
|
||||
*/
|
||||
static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded,
|
||||
DWORD cbEncoded, DWORD dwFlags, CERT_RDN_ATTR *attr, DWORD *pcbAttr)
|
||||
{
|
||||
@ -3657,7 +3676,8 @@ static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded,
|
||||
(LPSTR)(attr->Value.pbData +
|
||||
attr->Value.cbData);
|
||||
else
|
||||
attr->pszObjId = (LPSTR)originalData;
|
||||
attr->pszObjId =
|
||||
(LPSTR)originalData;
|
||||
size = bytesNeeded - size;
|
||||
ret = CRYPT_AsnDecodeOid(
|
||||
pbEncoded + objIdOfset,
|
||||
@ -3913,6 +3933,43 @@ static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
|
||||
|
||||
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, *pcbStructInfo);
|
||||
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += cbEncoded;
|
||||
if (!pvStructInfo)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if (*pcbStructInfo < bytesNeeded)
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
|
||||
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
blob->cbData = cbEncoded;
|
||||
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
|
||||
blob->pbData = (LPBYTE)pbEncoded;
|
||||
else
|
||||
{
|
||||
assert(blob->pbData);
|
||||
memcpy(blob->pbData, pbEncoded, blob->cbData);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
@ -3920,105 +3977,25 @@ static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
|
||||
CRYPT_ALGORITHM_IDENTIFIER *algo =
|
||||
(CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
|
||||
BOOL ret = TRUE;
|
||||
struct AsnDecodeSequenceItem items[] = {
|
||||
{ offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
|
||||
CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
|
||||
offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
|
||||
{ offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
|
||||
CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
|
||||
offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
|
||||
};
|
||||
|
||||
if (pbEncoded[0] == ASN_SEQUENCE)
|
||||
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, *pcbStructInfo);
|
||||
|
||||
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
|
||||
sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
|
||||
if (ret && pvStructInfo)
|
||||
{
|
||||
DWORD dataLen, bytesNeeded;
|
||||
|
||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
{
|
||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
||||
|
||||
bytesNeeded = sizeof(CRYPT_ALGORITHM_IDENTIFIER);
|
||||
if (dataLen)
|
||||
{
|
||||
const BYTE *ptr = pbEncoded + 1 + lenBytes;
|
||||
BYTE oidLenBytes;
|
||||
DWORD encodedOidLen, oidLen;
|
||||
|
||||
CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
|
||||
&encodedOidLen);
|
||||
oidLenBytes = GET_LEN_BYTES(ptr[1]);
|
||||
ret = CRYPT_AsnDecodeOid(ptr, cbEncoded - (ptr - pbEncoded),
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &oidLen);
|
||||
if (ret)
|
||||
{
|
||||
bytesNeeded += oidLen;
|
||||
ptr += 1 + encodedOidLen + oidLenBytes;
|
||||
/* The remaining bytes are just copied as-is, no decoding
|
||||
* is done.
|
||||
*/
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += cbEncoded - (ptr - pbEncoded);
|
||||
if (!algo)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if (*pcbStructInfo < bytesNeeded)
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get and sanity-check parameter length first */
|
||||
if (dataLen - 1 - oidLenBytes - encodedOidLen != 0)
|
||||
{
|
||||
DWORD paramsLen;
|
||||
|
||||
if ((ret = CRYPT_GetLen(ptr, cbEncoded -
|
||||
(ptr - pbEncoded), ¶msLen)))
|
||||
{
|
||||
BYTE paramsLenBytes = GET_LEN_BYTES(ptr[1]);
|
||||
|
||||
if (paramsLen != dataLen - encodedOidLen - 1 -
|
||||
oidLenBytes - 1 - paramsLenBytes)
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_CORRUPT);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
algo->Parameters.cbData = dataLen - 1 -
|
||||
oidLenBytes - encodedOidLen;
|
||||
if (algo->Parameters.cbData)
|
||||
{
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
{
|
||||
memcpy(algo->Parameters.pbData, ptr,
|
||||
algo->Parameters.cbData);
|
||||
algo->pszObjId = (LPSTR)algo->Parameters.pbData +
|
||||
algo->Parameters.cbData;
|
||||
}
|
||||
else
|
||||
{
|
||||
algo->Parameters.pbData = (BYTE *)ptr;
|
||||
algo->pszObjId = (LPSTR)algo->Parameters.pbData;
|
||||
}
|
||||
}
|
||||
else
|
||||
algo->pszObjId = (LPSTR)algo->Parameters.pbData;
|
||||
ptr = pbEncoded + 1 + lenBytes;
|
||||
ret = CRYPT_AsnDecodeOid(ptr,
|
||||
cbEncoded - (ptr - pbEncoded),
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
|
||||
algo->pszObjId, &oidLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_EOD);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
|
||||
debugstr_a(algo->pszObjId));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -4035,7 +4012,7 @@ static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
|
||||
{ offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
|
||||
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
|
||||
FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
|
||||
Algorithm.Parameters.pbData) },
|
||||
Algorithm.pszObjId) },
|
||||
{ offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
|
||||
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
|
||||
offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
|
||||
@ -4096,6 +4073,7 @@ static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
|
||||
*(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
|
||||
ret = TRUE;
|
||||
}
|
||||
TRACE("returning %d (%08lx)\n", ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4172,7 +4150,8 @@ static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
|
||||
DWORD i;
|
||||
|
||||
for (i = 0; i < dataLen; i++)
|
||||
entry->u.pwszURL[i] = (WCHAR)pbEncoded[1 + lenBytes + i];
|
||||
entry->u.pwszURL[i] =
|
||||
(WCHAR)pbEncoded[1 + lenBytes + i];
|
||||
entry->u.pwszURL[i] = 0;
|
||||
break;
|
||||
}
|
||||
@ -4264,7 +4243,8 @@ static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
|
||||
i < cEntry && ptr - pbEncoded - 1 - lenBytes <
|
||||
dataLen; i++)
|
||||
{
|
||||
info->rgAltEntry[i].u.pwszURL = (LPWSTR)nextData;
|
||||
info->rgAltEntry[i].u.pwszURL =
|
||||
(LPWSTR)nextData;
|
||||
size = bytesNeeded;
|
||||
ret = CRYPT_AsnDecodeAltNameEntry(ptr,
|
||||
cbEncoded - (ptr - pbEncoded), dwFlags,
|
||||
@ -4304,6 +4284,57 @@ static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct PATH_LEN_CONSTRAINT
|
||||
{
|
||||
BOOL fPathLenConstraint;
|
||||
DWORD dwPathLenConstraint;
|
||||
};
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
|
||||
if (cbEncoded)
|
||||
{
|
||||
if (pbEncoded[0] == ASN_INTEGER)
|
||||
{
|
||||
DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
|
||||
|
||||
if (!pvStructInfo)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if (*pcbStructInfo < bytesNeeded)
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct PATH_LEN_CONSTRAINT *constraint =
|
||||
(struct PATH_LEN_CONSTRAINT *)pvStructInfo;
|
||||
DWORD size = sizeof(constraint->dwPathLenConstraint);
|
||||
|
||||
ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
|
||||
pbEncoded, cbEncoded, 0, NULL,
|
||||
&constraint->dwPathLenConstraint, &size);
|
||||
if (ret)
|
||||
constraint->fPathLenConstraint = TRUE;
|
||||
TRACE("got an int, dwPathLenConstraint is %ld\n",
|
||||
constraint->dwPathLenConstraint);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_CORRUPT);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
TRACE("returning %d (%08lx)\n", ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
@ -4312,92 +4343,17 @@ static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
|
||||
|
||||
__TRY
|
||||
{
|
||||
if (pbEncoded[0] == ASN_SEQUENCE)
|
||||
{
|
||||
DWORD dataLen;
|
||||
struct AsnDecodeSequenceItem items[] = {
|
||||
{ offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA), CRYPT_AsnDecodeBool,
|
||||
sizeof(BOOL), TRUE, FALSE, 0, 0 },
|
||||
{ offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fPathLenConstraint),
|
||||
CRYPT_AsnDecodePathLenConstraint, sizeof(struct PATH_LEN_CONSTRAINT),
|
||||
TRUE, FALSE, 0, 0 },
|
||||
};
|
||||
|
||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
{
|
||||
/* sanity-check length, space enough for 7 bytes of integer and
|
||||
* 3 bytes of bool
|
||||
*/
|
||||
if (dataLen > 10)
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_CORRUPT);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD bytesNeeded = sizeof(CERT_BASIC_CONSTRAINTS2_INFO);
|
||||
|
||||
if (!pvStructInfo)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else
|
||||
{
|
||||
BYTE lenBytes;
|
||||
CERT_BASIC_CONSTRAINTS2_INFO info = { 0 };
|
||||
|
||||
lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
||||
pbEncoded += 1 + lenBytes;
|
||||
cbEncoded -= 1 + lenBytes;
|
||||
if (cbEncoded)
|
||||
{
|
||||
DWORD size;
|
||||
|
||||
if (pbEncoded[0] == ASN_BOOL)
|
||||
{
|
||||
size = sizeof(BOOL);
|
||||
ret = CRYPT_AsnDecodeBool(dwCertEncodingType,
|
||||
NULL, pbEncoded, cbEncoded,
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
&info.fCA, &size);
|
||||
if (ret)
|
||||
{
|
||||
cbEncoded -= 2 + pbEncoded[1];
|
||||
pbEncoded += 2 + pbEncoded[1];
|
||||
}
|
||||
}
|
||||
if (ret && cbEncoded && pbEncoded[0] == ASN_INTEGER)
|
||||
{
|
||||
size = sizeof(info.dwPathLenConstraint);
|
||||
ret = CRYPT_AsnDecodeInt(dwCertEncodingType,
|
||||
X509_INTEGER, pbEncoded, cbEncoded, 0, NULL,
|
||||
&info.dwPathLenConstraint, &size);
|
||||
if (ret)
|
||||
{
|
||||
cbEncoded -= 2 + pbEncoded[1];
|
||||
pbEncoded += 2 + pbEncoded[1];
|
||||
if (cbEncoded)
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_CORRUPT);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
info.fPathLenConstraint = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
|
||||
pDecodePara, pvStructInfo, pcbStructInfo,
|
||||
bytesNeeded)))
|
||||
{
|
||||
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
||||
pvStructInfo = *(BYTE **)pvStructInfo;
|
||||
memcpy(pvStructInfo, &info,
|
||||
sizeof(CERT_BASIC_CONSTRAINTS2_INFO));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
|
||||
sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, pcbStructInfo, NULL);
|
||||
}
|
||||
__EXCEPT(page_fault)
|
||||
{
|
||||
@ -4482,47 +4438,92 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, *pcbStructInfo);
|
||||
|
||||
if (pbEncoded[0] == ASN_OCTETSTRING)
|
||||
{
|
||||
DWORD bytesNeeded, dataLen;
|
||||
|
||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
{
|
||||
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
|
||||
bytesNeeded = sizeof(CRYPT_DATA_BLOB);
|
||||
else
|
||||
bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
|
||||
if (!pvStructInfo)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if (*pcbStructInfo < bytesNeeded)
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPT_DATA_BLOB *blob;
|
||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
||||
|
||||
blob = (CRYPT_DATA_BLOB *)pvStructInfo;
|
||||
blob->cbData = dataLen;
|
||||
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
|
||||
blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
|
||||
else
|
||||
{
|
||||
assert(blob->pbData);
|
||||
if (blob->cbData)
|
||||
memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
|
||||
blob->cbData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, *pcbStructInfo);
|
||||
|
||||
__TRY
|
||||
{
|
||||
if (pbEncoded[0] == ASN_OCTETSTRING)
|
||||
DWORD bytesNeeded;
|
||||
|
||||
if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
|
||||
lpszStructType, pbEncoded, cbEncoded,
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
|
||||
{
|
||||
DWORD bytesNeeded, dataLen;
|
||||
|
||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
if (!pvStructInfo)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
|
||||
pvStructInfo, pcbStructInfo, bytesNeeded)))
|
||||
{
|
||||
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
|
||||
bytesNeeded = sizeof(CRYPT_DATA_BLOB);
|
||||
else
|
||||
bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
|
||||
if (!pvStructInfo)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
|
||||
pvStructInfo, pcbStructInfo, bytesNeeded)))
|
||||
{
|
||||
CRYPT_DATA_BLOB *blob;
|
||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
||||
CRYPT_DATA_BLOB *blob;
|
||||
|
||||
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
||||
pvStructInfo = *(BYTE **)pvStructInfo;
|
||||
blob = (CRYPT_DATA_BLOB *)pvStructInfo;
|
||||
blob->cbData = dataLen;
|
||||
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
|
||||
blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
|
||||
else
|
||||
{
|
||||
blob->pbData = (BYTE *)pvStructInfo +
|
||||
sizeof(CRYPT_DATA_BLOB);
|
||||
if (blob->cbData)
|
||||
memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
|
||||
blob->cbData);
|
||||
}
|
||||
}
|
||||
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
||||
pvStructInfo = *(BYTE **)pvStructInfo;
|
||||
blob = (CRYPT_DATA_BLOB *)pvStructInfo;
|
||||
blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
|
||||
ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
|
||||
lpszStructType, pbEncoded, cbEncoded,
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
|
||||
&bytesNeeded);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -4600,6 +4601,7 @@ static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
TRACE("returning %d (%08lx)\n", ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4644,6 +4646,7 @@ static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
|
||||
ret = FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
TRACE("returning %d (%08lx)\n", ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -840,6 +840,8 @@ static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
|
||||
static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
|
||||
0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
|
||||
0x6f, 0x72, 0x67 };
|
||||
static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
|
||||
0x575b, 0 };
|
||||
static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
|
||||
static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
|
||||
0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
|
||||
@ -849,7 +851,6 @@ static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
|
||||
|
||||
static void test_encodeAltName(DWORD dwEncoding)
|
||||
{
|
||||
static const WCHAR nihongo[] = { 0x226f, 0x575b, 0 };
|
||||
CERT_ALT_NAME_INFO info = { 0 };
|
||||
CERT_ALT_NAME_ENTRY entry = { 0 };
|
||||
BYTE *buf = NULL;
|
||||
@ -897,11 +898,15 @@ static void test_encodeAltName(DWORD dwEncoding)
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* Now with the URL containing an invalid IA5 char */
|
||||
U(entry).pwszURL = (LPWSTR)nihongo;
|
||||
U(entry).pwszURL = (LPWSTR)nihongoURL;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
|
||||
"Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
|
||||
/* The first invalid character is at index 7 */
|
||||
ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
|
||||
"Expected invalid char at index 7, got %ld\n",
|
||||
GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
|
||||
/* Now with the URL missing a scheme */
|
||||
U(entry).pwszURL = (LPWSTR)dnsName;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
|
||||
@ -1960,16 +1965,13 @@ static void test_decodeCertToBeSigned(DWORD dwEncoding)
|
||||
/* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
|
||||
* minimum a cert must have a non-zero serial number, an issuer, and a
|
||||
* subject.
|
||||
* It's hard to match the errors precisely sometimes, so accept one
|
||||
* that only wine gives as long as it fails
|
||||
*/
|
||||
for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
|
||||
{
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
|
||||
corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
(BYTE *)&buf, &size);
|
||||
ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
|
||||
GetLastError() == CRYPT_E_ASN1_BADTAG),
|
||||
ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
|
||||
"Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
|
||||
}
|
||||
/* Now check with serial number, subject and issuer specified */
|
||||
@ -2205,11 +2207,7 @@ static void test_decodeCRLToBeSigned(DWORD dwEncoding)
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
|
||||
corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
(BYTE *)&buf, &size);
|
||||
/* It's hard to match the errors precisely sometimes, so accept one
|
||||
* that only wine gives as long as it fails
|
||||
*/
|
||||
ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
|
||||
GetLastError() == CRYPT_E_ASN1_BADTAG),
|
||||
ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
|
||||
"Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
|
||||
}
|
||||
/* at a minimum, a CRL must contain an issuer: */
|
||||
|
Loading…
Reference in New Issue
Block a user