//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1996 - 1996 // // 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 // // // Notes: According to the : // For UTCTime. Where YY is greater than 50, the year shall // be interpreted as 19YY. Where YY is less than or equal to // 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 #include "badstrfunctions.h" //////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // These are the old 4.0 versions of these routines. #define atol StrToInt char * __cdecl _ltoa(long l, char * psz, int) {wnsprintf(psz, 10, "%d", l); return psz; } ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// // // UTCTime in X.509 certs are represented using a 2-digit year // field (yuk! but true). // // According to IETF draft, YY years greater than this are // to be interpreted as 19YY; YY years less than this are 20YY. Sigh. // #define MAGICYEAR 50 #define YEARFIRST 1951 #define YEARLAST 2050 #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; } if ((fResult = SystemTimeToFileTime(&stmDiff, &ftmDiff))) { if (mindiff > 0) *((_int64 *) pFileTime) += *((_int64 *) &ftmDiff); else *((_int64 *) pFileTime) -= *((_int64 *) &ftmDiff); } 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); }