crypt32: Use simpler form for internal time decoding functions.

This commit is contained in:
Juan Lang 2007-09-17 17:02:58 -07:00 committed by Alexandre Julliard
parent 52be131a29
commit a538e95c1d
1 changed files with 165 additions and 147 deletions

View File

@ -3444,166 +3444,166 @@ static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
#define MIN_ENCODED_TIME_LENGTH 10 #define MIN_ENCODED_TIME_LENGTH 10
static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
DWORD *pcbDecoded)
{
BOOL ret = FALSE;
if (pbEncoded[0] == ASN_UTCTIME)
{
if (cbEncoded <= 1)
SetLastError(CRYPT_E_ASN1_EOD);
else if (pbEncoded[1] > 0x7f)
{
/* long-form date strings really can't be valid */
SetLastError(CRYPT_E_ASN1_CORRUPT);
}
else
{
SYSTEMTIME sysTime = { 0 };
BYTE len = pbEncoded[1];
if (len < MIN_ENCODED_TIME_LENGTH)
SetLastError(CRYPT_E_ASN1_CORRUPT);
else
{
ret = TRUE;
pbEncoded += 2;
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
if (sysTime.wYear >= 50)
sysTime.wYear += 1900;
else
sysTime.wYear += 2000;
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
if (ret && len > 0)
{
if (len >= 2 && isdigit(*pbEncoded) &&
isdigit(*(pbEncoded + 1)))
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
sysTime.wSecond);
else if (isdigit(*pbEncoded))
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
sysTime.wSecond);
if (ret)
ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
&sysTime);
}
if (ret)
{
if (!pvStructInfo)
*pcbStructInfo = sizeof(FILETIME);
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL,
pvStructInfo, pcbStructInfo, sizeof(FILETIME))))
ret = SystemTimeToFileTime(&sysTime,
(FILETIME *)pvStructInfo);
}
}
}
}
else
SetLastError(CRYPT_E_ASN1_BADTAG);
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{ {
BOOL ret; BOOL ret = FALSE;
if (!pvStructInfo)
{
*pcbStructInfo = sizeof(FILETIME);
return TRUE;
}
__TRY __TRY
{ {
ret = TRUE; DWORD bytesNeeded;
if (pbEncoded[0] == ASN_UTCTIME)
{
if (cbEncoded <= 1)
{
SetLastError(CRYPT_E_ASN1_EOD);
ret = FALSE;
}
else if (pbEncoded[1] > 0x7f)
{
/* long-form date strings really can't be valid */
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
else
{
SYSTEMTIME sysTime = { 0 };
BYTE len = pbEncoded[1];
if (len < MIN_ENCODED_TIME_LENGTH) ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
{ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
SetLastError(CRYPT_E_ASN1_CORRUPT); if (ret)
ret = FALSE;
}
else
{
pbEncoded += 2;
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
if (sysTime.wYear >= 50)
sysTime.wYear += 1900;
else
sysTime.wYear += 2000;
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
if (ret && len > 0)
{
if (len >= 2 && isdigit(*pbEncoded) &&
isdigit(*(pbEncoded + 1)))
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
sysTime.wSecond);
else if (isdigit(*pbEncoded))
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
sysTime.wSecond);
if (ret)
ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
&sysTime);
}
if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo,
sizeof(FILETIME))))
{
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
ret = SystemTimeToFileTime(&sysTime,
(FILETIME *)pvStructInfo);
}
}
}
}
else
{ {
SetLastError(CRYPT_E_ASN1_BADTAG); if (!pvStructInfo)
ret = FALSE; *pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
{
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
&bytesNeeded, NULL);
}
} }
} }
__EXCEPT_PAGE_FAULT __EXCEPT_PAGE_FAULT
{ {
SetLastError(STATUS_ACCESS_VIOLATION); SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
} }
__ENDTRY __ENDTRY
return ret; return ret;
} }
static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType, static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) DWORD *pcbDecoded)
{ {
BOOL ret; BOOL ret = FALSE;
if (!pvStructInfo) if (pbEncoded[0] == ASN_GENERALTIME)
{ {
*pcbStructInfo = sizeof(FILETIME); if (cbEncoded <= 1)
return TRUE; SetLastError(CRYPT_E_ASN1_EOD);
} else if (pbEncoded[1] > 0x7f)
__TRY
{
ret = TRUE;
if (pbEncoded[0] == ASN_GENERALTIME)
{ {
if (cbEncoded <= 1) /* long-form date strings really can't be valid */
{ SetLastError(CRYPT_E_ASN1_CORRUPT);
SetLastError(CRYPT_E_ASN1_EOD); }
ret = FALSE; else
} {
else if (pbEncoded[1] > 0x7f) BYTE len = pbEncoded[1];
{
/* long-form date strings really can't be valid */ if (len < MIN_ENCODED_TIME_LENGTH)
SetLastError(CRYPT_E_ASN1_CORRUPT); SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
else else
{ {
BYTE len = pbEncoded[1]; SYSTEMTIME sysTime = { 0 };
if (len < MIN_ENCODED_TIME_LENGTH) ret = TRUE;
pbEncoded += 2;
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
if (ret && len > 0)
{ {
SetLastError(CRYPT_E_ASN1_CORRUPT); CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
ret = FALSE; sysTime.wMinute);
}
else
{
SYSTEMTIME sysTime = { 0 };
pbEncoded += 2;
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
if (ret && len > 0) if (ret && len > 0)
{
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
sysTime.wMinute); sysTime.wSecond);
if (ret && len > 0) if (ret && len > 0 && (*pbEncoded == '.' ||
CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, *pbEncoded == ','))
sysTime.wSecond); {
if (ret && len > 0 && (*pbEncoded == '.' || BYTE digits;
*pbEncoded == ','))
{
BYTE digits;
pbEncoded++; pbEncoded++;
len--; len--;
/* workaround macro weirdness */ /* workaround macro weirdness */
digits = min(len, 3); digits = min(len, 3);
CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits, CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
sysTime.wMilliseconds); sysTime.wMilliseconds);
}
if (ret)
ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
&sysTime);
} }
if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, if (ret)
pDecodePara, pvStructInfo, pcbStructInfo, ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
sizeof(FILETIME)))) &sysTime);
}
if (ret)
{
if (!pvStructInfo)
*pcbStructInfo = sizeof(FILETIME);
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL,
pvStructInfo, pcbStructInfo, sizeof(FILETIME))))
{ {
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo; pvStructInfo = *(BYTE **)pvStructInfo;
@ -3613,18 +3613,31 @@ static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
} }
} }
} }
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
} }
__EXCEPT_PAGE_FAULT else
SetLastError(CRYPT_E_ASN1_BADTAG);
return ret;
}
static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
DWORD *pcbDecoded)
{
BOOL ret;
InternalDecodeFunc decode = NULL;
if (pbEncoded[0] == ASN_UTCTIME)
decode = CRYPT_AsnDecodeUtcTimeInternal;
else if (pbEncoded[0] == ASN_GENERALTIME)
decode = CRYPT_AsnDecodeGeneralizedTime;
if (decode)
ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
pcbStructInfo, pcbDecoded);
else
{ {
SetLastError(STATUS_ACCESS_VIOLATION); SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE; ret = FALSE;
} }
__ENDTRY
return ret; return ret;
} }
@ -3636,18 +3649,23 @@ static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
__TRY __TRY
{ {
if (pbEncoded[0] == ASN_UTCTIME) DWORD bytesNeeded;
ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
pcbStructInfo); dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
else if (pbEncoded[0] == ASN_GENERALTIME) if (ret)
ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo);
else
{ {
SetLastError(CRYPT_E_ASN1_BADTAG); if (!pvStructInfo)
ret = FALSE; *pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo, bytesNeeded)))
{
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
&bytesNeeded, NULL);
}
} }
} }
__EXCEPT_PAGE_FAULT __EXCEPT_PAGE_FAULT