427 lines
11 KiB
C++
427 lines
11 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: ossconv.cpp
|
|
//
|
|
// Contents: Conversion APIs to/from OSS ASN.1 data structures
|
|
//
|
|
// Functions: OssConvToObjectIdentifier
|
|
// OssConvFromObjectIdentifier
|
|
// OssConvToUTCTime
|
|
// OssConvFromUTCTime
|
|
// OssConvToGeneralizedTime
|
|
// OssConvFromGeneralizedTime
|
|
// OssConvToChoiceOfTime
|
|
// OssConvFromChoiceOfTime
|
|
// OssConvToAttribute
|
|
// OssConvToAlgorithmIdentifier
|
|
// OssConvFromAlgorithmIdentifier
|
|
//
|
|
// According to the <draft-ietf-pkix-ipki-part1-10.txt> :
|
|
// For UTCTime. Where YY is greater than or equal to 50, the year shall
|
|
// be interpreted as 19YY. Where YY is less than
|
|
// 50, the year shall be interpreted as 20YY.
|
|
//
|
|
// History: 28-Mar-96 philh created
|
|
// 03-May-96 kevinr merged from wincrmsg
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "global.hxx"
|
|
#include <dbgdef.h>
|
|
|
|
//
|
|
// UTCTime in X.509 certs are represented using a 2-digit year
|
|
// field (yuk! but true).
|
|
//
|
|
// According to IETF draft, YY years greater or equal than this are
|
|
// to be interpreted as 19YY; YY years less than this are 20YY. Sigh.
|
|
//
|
|
#define MAGICYEAR 50
|
|
|
|
#define YEARFIRST 1950
|
|
#define YEARLAST 2049
|
|
#define YEARFIRSTGENERALIZED 2050
|
|
|
|
inline BOOL my_isdigit( char ch)
|
|
{
|
|
return (ch >= '0') && (ch <= '9');
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert the ascii string ("1.2.9999") to OSS's Object Identifier
|
|
// represented as an array of unsigned longs.
|
|
//
|
|
// Returns TRUE for a successful conversion.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
OssConvToObjectIdentifier(
|
|
IN LPCSTR pszObjId,
|
|
IN OUT unsigned short *pCount,
|
|
OUT unsigned long rgulValue[]
|
|
)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
unsigned short c = 0;
|
|
LPSTR psz = (LPSTR) pszObjId;
|
|
char ch;
|
|
|
|
if (psz) {
|
|
unsigned short cMax = *pCount;
|
|
unsigned long *pul = rgulValue;
|
|
while ((ch = *psz) != '\0' && c++ < cMax) {
|
|
*pul++ = (unsigned long)atol(psz);
|
|
while (my_isdigit(ch = *psz++))
|
|
;
|
|
if (ch != '.')
|
|
break;
|
|
}
|
|
if (ch != '\0')
|
|
fResult = FALSE;
|
|
}
|
|
*pCount = c;
|
|
return fResult;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert from OSS's Object Identifier represented as an array of
|
|
// unsigned longs to an ascii string ("1.2.9999").
|
|
//
|
|
// Returns TRUE for a successful conversion
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
OssConvFromObjectIdentifier(
|
|
IN unsigned short Count,
|
|
IN unsigned long rgulValue[],
|
|
OUT LPSTR pszObjId,
|
|
IN OUT DWORD *pcbObjId
|
|
)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
LONG lRemain;
|
|
|
|
if (pszObjId == NULL)
|
|
*pcbObjId = 0;
|
|
|
|
lRemain = (LONG) *pcbObjId;
|
|
if (Count == 0) {
|
|
if (--lRemain > 0)
|
|
pszObjId++;
|
|
} else {
|
|
char rgch[36];
|
|
LONG lData;
|
|
unsigned long *pul = rgulValue;
|
|
for (; Count > 0; Count--, pul++) {
|
|
_ltoa(*pul, rgch, 10);
|
|
lData = strlen(rgch);
|
|
lRemain -= lData + 1;
|
|
if (lRemain >= 0) {
|
|
if (lData > 0) {
|
|
memcpy(pszObjId, rgch, lData);
|
|
pszObjId += lData;
|
|
}
|
|
*pszObjId++ = '.';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lRemain >= 0) {
|
|
*(pszObjId -1) = '\0';
|
|
*pcbObjId = *pcbObjId - (DWORD) lRemain;
|
|
} else {
|
|
*pcbObjId = *pcbObjId + (DWORD) -lRemain;
|
|
if (pszObjId) {
|
|
SetLastError((DWORD) ERROR_MORE_DATA);
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Adjust FILETIME for timezone.
|
|
//
|
|
// Returns FALSE iff conversion failed.
|
|
//--------------------------------------------------------------------------
|
|
static BOOL AdjustFileTime(
|
|
IN OUT LPFILETIME pFileTime,
|
|
IN short mindiff,
|
|
IN ossBoolean utc
|
|
)
|
|
{
|
|
if (utc || mindiff == 0)
|
|
return TRUE;
|
|
|
|
BOOL fResult;
|
|
SYSTEMTIME stmDiff;
|
|
FILETIME ftmDiff;
|
|
short absmindiff;
|
|
|
|
memset(&stmDiff, 0, sizeof(stmDiff));
|
|
// Note: FILETIME is 100 nanoseconds interval since January 1, 1601
|
|
stmDiff.wYear = 1601;
|
|
stmDiff.wMonth = 1;
|
|
stmDiff.wDay = 1;
|
|
|
|
absmindiff = mindiff > 0 ? mindiff : -mindiff;
|
|
stmDiff.wHour = absmindiff / 60;
|
|
stmDiff.wMinute = absmindiff % 60;
|
|
if (stmDiff.wHour >= 24) {
|
|
stmDiff.wDay += stmDiff.wHour / 24;
|
|
stmDiff.wHour %= 24;
|
|
}
|
|
|
|
// Note, FILETIME is only 32 bit aligned. __int64 is 64 bit aligned.
|
|
if ((fResult = SystemTimeToFileTime(&stmDiff, &ftmDiff))) {
|
|
unsigned __int64 uTime;
|
|
unsigned __int64 uDiff;
|
|
|
|
memcpy(&uTime, pFileTime, sizeof(uTime));
|
|
memcpy(&uDiff, &ftmDiff, sizeof(uDiff));
|
|
|
|
if (mindiff > 0)
|
|
uTime += uDiff;
|
|
else
|
|
uTime -= uDiff;
|
|
|
|
memcpy(pFileTime, &uTime, sizeof(*pFileTime));
|
|
}
|
|
return fResult;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert FILETIME to OSS's UTCTime.
|
|
//
|
|
// Returns TRUE for a successful conversion
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
OssConvToUTCTime(
|
|
IN LPFILETIME pFileTime,
|
|
OUT UTCTime *pOssTime
|
|
)
|
|
{
|
|
BOOL fRet;
|
|
SYSTEMTIME t;
|
|
|
|
memset(pOssTime, 0, sizeof(*pOssTime));
|
|
if (!FileTimeToSystemTime(pFileTime, &t))
|
|
goto FileTimeToSystemTimeError;
|
|
if (t.wYear < YEARFIRST || t.wYear > YEARLAST)
|
|
goto YearRangeError;
|
|
|
|
pOssTime->year = t.wYear % 100;
|
|
pOssTime->month = t.wMonth;
|
|
pOssTime->day = t.wDay;
|
|
pOssTime->hour = t.wHour;
|
|
pOssTime->minute = t.wMinute;
|
|
pOssTime->second = t.wSecond;
|
|
pOssTime->utc = TRUE;
|
|
|
|
fRet = TRUE;
|
|
CommonReturn:
|
|
return fRet;
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto CommonReturn;
|
|
TRACE_ERROR(FileTimeToSystemTimeError)
|
|
TRACE_ERROR(YearRangeError)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert from OSS's UTCTime to FILETIME.
|
|
//
|
|
// Returns TRUE for a successful conversion
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
OssConvFromUTCTime(
|
|
IN UTCTime *pOssTime,
|
|
OUT LPFILETIME pFileTime
|
|
)
|
|
{
|
|
BOOL fRet;
|
|
SYSTEMTIME t;
|
|
memset(&t, 0, sizeof(t));
|
|
|
|
t.wYear = pOssTime->year >= MAGICYEAR ?
|
|
(1900 + pOssTime->year) : (2000 + pOssTime->year);
|
|
t.wMonth = pOssTime->month;
|
|
t.wDay = pOssTime->day;
|
|
t.wHour = pOssTime->hour;
|
|
t.wMinute = pOssTime->minute;
|
|
t.wSecond = pOssTime->second;
|
|
|
|
if (!SystemTimeToFileTime(&t, pFileTime))
|
|
goto SystemTimeToFileTimeError;
|
|
fRet = AdjustFileTime(
|
|
pFileTime,
|
|
pOssTime->mindiff,
|
|
pOssTime->utc
|
|
);
|
|
CommonReturn:
|
|
return fRet;
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto CommonReturn;
|
|
TRACE_ERROR(SystemTimeToFileTimeError)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert FILETIME to OSS's GeneralizedTime.
|
|
//
|
|
// Returns TRUE for a successful conversion
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
OssConvToGeneralizedTime(
|
|
IN LPFILETIME pFileTime,
|
|
OUT GeneralizedTime *pOssTime
|
|
)
|
|
{
|
|
BOOL fRet;
|
|
SYSTEMTIME t;
|
|
|
|
memset(pOssTime, 0, sizeof(*pOssTime));
|
|
if (!FileTimeToSystemTime(pFileTime, &t))
|
|
goto FileTimeToSystemTimeError;
|
|
pOssTime->year = t.wYear;
|
|
pOssTime->month = t.wMonth;
|
|
pOssTime->day = t.wDay;
|
|
pOssTime->hour = t.wHour;
|
|
pOssTime->minute = t.wMinute;
|
|
pOssTime->second = t.wSecond;
|
|
pOssTime->millisec = t.wMilliseconds;
|
|
pOssTime->utc = TRUE;
|
|
|
|
fRet = TRUE;
|
|
CommonReturn:
|
|
return fRet;
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto CommonReturn;
|
|
TRACE_ERROR(FileTimeToSystemTimeError)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert from OSS's GeneralizedTime to FILETIME.
|
|
//
|
|
// Returns TRUE for a successful conversion
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
OssConvFromGeneralizedTime(
|
|
IN GeneralizedTime *pOssTime,
|
|
OUT LPFILETIME pFileTime
|
|
)
|
|
{
|
|
BOOL fRet;
|
|
SYSTEMTIME t;
|
|
memset(&t, 0, sizeof(t));
|
|
|
|
t.wYear = pOssTime->year;
|
|
t.wMonth = pOssTime->month;
|
|
t.wDay = pOssTime->day;
|
|
t.wHour = pOssTime->hour;
|
|
t.wMinute = pOssTime->minute;
|
|
t.wSecond = pOssTime->second;
|
|
t.wMilliseconds = pOssTime->millisec;
|
|
|
|
if (!SystemTimeToFileTime(&t, pFileTime))
|
|
goto SystemTimeToFileTimeError;
|
|
fRet = AdjustFileTime(
|
|
pFileTime,
|
|
pOssTime->mindiff,
|
|
pOssTime->utc
|
|
);
|
|
CommonReturn:
|
|
return fRet;
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto CommonReturn;
|
|
TRACE_ERROR(SystemTimeToFileTimeError)
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert FILETIME to OSS's UTCTime or GeneralizedTime.
|
|
//
|
|
// If 1950 < FILETIME < 2005, then UTCTime is chosen. Otherwise,
|
|
// GeneralizedTime is chosen. GeneralizedTime values shall not include
|
|
// fractional seconds.
|
|
//
|
|
// Returns TRUE for a successful conversion
|
|
//
|
|
// Note, in asn1hdr.h, UTCTime has same typedef as GeneralizedTime.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
OssConvToChoiceOfTime(
|
|
IN LPFILETIME pFileTime,
|
|
OUT WORD *pwChoice,
|
|
OUT GeneralizedTime *pOssTime
|
|
)
|
|
{
|
|
BOOL fRet;
|
|
SYSTEMTIME t;
|
|
|
|
memset(pOssTime, 0, sizeof(*pOssTime));
|
|
if (!FileTimeToSystemTime(pFileTime, &t))
|
|
goto FileTimeToSystemTimeError;
|
|
if (t.wYear < YEARFIRST || t.wYear >= YEARFIRSTGENERALIZED) {
|
|
*pwChoice = OSS_GENERALIZED_TIME_CHOICE;
|
|
pOssTime->year = t.wYear;
|
|
} else {
|
|
*pwChoice = OSS_UTC_TIME_CHOICE;
|
|
pOssTime->year = t.wYear % 100;
|
|
}
|
|
pOssTime->month = t.wMonth;
|
|
pOssTime->day = t.wDay;
|
|
pOssTime->hour = t.wHour;
|
|
pOssTime->minute = t.wMinute;
|
|
pOssTime->second = t.wSecond;
|
|
pOssTime->utc = TRUE;
|
|
|
|
fRet = TRUE;
|
|
CommonReturn:
|
|
return fRet;
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
*pwChoice = 0;
|
|
goto CommonReturn;
|
|
TRACE_ERROR(FileTimeToSystemTimeError)
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert from OSS's UTCTime or GeneralizedTime to FILETIME.
|
|
//
|
|
// Returns TRUE for a successful conversion.
|
|
//
|
|
// Note, in asn1hdr.h, UTCTime has same typedef as GeneralizedTime.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
OssConvFromChoiceOfTime(
|
|
IN WORD wChoice,
|
|
IN GeneralizedTime *pOssTime,
|
|
OUT LPFILETIME pFileTime
|
|
)
|
|
{
|
|
if (OSS_UTC_TIME_CHOICE == wChoice)
|
|
return OssConvFromUTCTime(pOssTime, pFileTime);
|
|
else
|
|
return OssConvFromGeneralizedTime(pOssTime, pFileTime);
|
|
}
|