967 lines
26 KiB
C++
967 lines
26 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1995 - 1999
|
||
|
//
|
||
|
// File: ossutil.cpp
|
||
|
//
|
||
|
// Contents: OSS ASN.1 compiler utility helper functions.
|
||
|
//
|
||
|
// Functions: OssUtilReverseBytes
|
||
|
// OssUtilAllocAndReverseBytes
|
||
|
// OssUtilGetOctetString
|
||
|
// OssUtilSetHugeInteger
|
||
|
// OssUtilFreeHugeInteger
|
||
|
// OssUtilGetHugeInteger
|
||
|
// OssUtilSetHugeUINT
|
||
|
// OssUtilGetHugeUINT
|
||
|
// OssUtilSetBitString
|
||
|
// OssUtilGetBitString
|
||
|
// OssUtilSetBitStringWithoutTrailingZeroes
|
||
|
// OssUtilGetIA5String
|
||
|
// OssUtilSetUnicodeConvertedToIA5String
|
||
|
// OssUtilFreeUnicodeConvertedToIA5String
|
||
|
// OssUtilGetIA5StringConvertedToUnicode
|
||
|
// OssUtilGetBMPString
|
||
|
// OssUtilSetAny
|
||
|
// OssUtilGetAny
|
||
|
// OssUtilEncodeInfoEx
|
||
|
// OssUtilEncodeInfo
|
||
|
// OssUtilDecodeAndAllocInfo
|
||
|
// OssUtilFreeInfo
|
||
|
// OssUtilAllocStructInfoEx
|
||
|
// OssUtilDecodeAndAllocInfoEx
|
||
|
//
|
||
|
// The Get functions decrement *plRemainExtra and advance
|
||
|
// *ppbExtra. When *plRemainExtra becomes negative, the functions continue
|
||
|
// with the length calculation but stop doing any copies.
|
||
|
// The functions don't return an error for a negative *plRemainExtra.
|
||
|
//
|
||
|
// History: 17-Nov-96 philh created
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#include "global.hxx"
|
||
|
#include <dbgdef.h>
|
||
|
|
||
|
// All the *pvInfo extra stuff needs to be aligned
|
||
|
#define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Reverses a buffer of bytes in place
|
||
|
//--------------------------------------------------------------------------
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilReverseBytes(
|
||
|
IN OUT PBYTE pbIn,
|
||
|
IN DWORD cbIn
|
||
|
)
|
||
|
{
|
||
|
// reverse in place
|
||
|
PBYTE pbLo;
|
||
|
PBYTE pbHi;
|
||
|
BYTE bTmp;
|
||
|
|
||
|
if (0 == cbIn)
|
||
|
return;
|
||
|
|
||
|
for (pbLo = pbIn, pbHi = pbIn + cbIn - 1; pbLo < pbHi; pbHi--, pbLo++) {
|
||
|
bTmp = *pbHi;
|
||
|
*pbHi = *pbLo;
|
||
|
*pbLo = bTmp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Reverses a buffer of bytes to a new buffer. OssUtilFree() must be
|
||
|
// called to free allocated bytes.
|
||
|
//--------------------------------------------------------------------------
|
||
|
PBYTE
|
||
|
WINAPI
|
||
|
OssUtilAllocAndReverseBytes(
|
||
|
IN PBYTE pbIn,
|
||
|
IN DWORD cbIn
|
||
|
)
|
||
|
{
|
||
|
PBYTE pbOut;
|
||
|
PBYTE pbSrc;
|
||
|
PBYTE pbDst;
|
||
|
DWORD cb;
|
||
|
|
||
|
if (NULL == (pbOut = (PBYTE)OssUtilAlloc(cbIn)))
|
||
|
return NULL;
|
||
|
|
||
|
for (pbSrc = pbIn, pbDst = pbOut + cbIn - 1, cb = cbIn; cb > 0; cb--)
|
||
|
*pbDst-- = *pbSrc++;
|
||
|
return pbOut;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Get Octet String
|
||
|
//--------------------------------------------------------------------------
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilGetOctetString(
|
||
|
IN unsigned int OssLength,
|
||
|
IN unsigned char *OssValue,
|
||
|
IN DWORD dwFlags,
|
||
|
OUT PCRYPT_DATA_BLOB pInfo,
|
||
|
IN OUT BYTE **ppbExtra,
|
||
|
IN OUT LONG *plRemainExtra
|
||
|
)
|
||
|
{
|
||
|
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) {
|
||
|
if (*plRemainExtra >= 0) {
|
||
|
pInfo->cbData = OssLength;
|
||
|
pInfo->pbData = OssValue;
|
||
|
}
|
||
|
} else {
|
||
|
LONG lRemainExtra = *plRemainExtra;
|
||
|
BYTE *pbExtra = *ppbExtra;
|
||
|
LONG lAlignExtra;
|
||
|
LONG lData;
|
||
|
|
||
|
lData = (LONG) OssLength;
|
||
|
lAlignExtra = INFO_LEN_ALIGN(lData);
|
||
|
lRemainExtra -= lAlignExtra;
|
||
|
if (lRemainExtra >= 0) {
|
||
|
if (lData > 0) {
|
||
|
pInfo->pbData = pbExtra;
|
||
|
pInfo->cbData = (DWORD) lData;
|
||
|
memcpy(pbExtra, OssValue, lData);
|
||
|
} else
|
||
|
memset(pInfo, 0, sizeof(*pInfo));
|
||
|
pbExtra += lAlignExtra;
|
||
|
}
|
||
|
*plRemainExtra = lRemainExtra;
|
||
|
*ppbExtra = pbExtra;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Set/Free/Get HugeInteger
|
||
|
//
|
||
|
// BYTE reversal::
|
||
|
// - this only needs to be done for little endian processors
|
||
|
//
|
||
|
// For OssUtilSetInteger, OssUtilFreeInteger must be called to free
|
||
|
// the allocated OssValue.
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
OssUtilSetHugeInteger(
|
||
|
IN PCRYPT_INTEGER_BLOB pInfo,
|
||
|
OUT unsigned int *pOssLength,
|
||
|
OUT unsigned char **ppOssValue
|
||
|
)
|
||
|
{
|
||
|
if (pInfo->cbData > 0) {
|
||
|
if (NULL == (*ppOssValue = OssUtilAllocAndReverseBytes(
|
||
|
pInfo->pbData, pInfo->cbData))) {
|
||
|
*pOssLength = 0;
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else
|
||
|
*ppOssValue = NULL;
|
||
|
*pOssLength = pInfo->cbData;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilFreeHugeInteger(
|
||
|
IN unsigned char *pOssValue
|
||
|
)
|
||
|
{
|
||
|
// Only for BYTE reversal
|
||
|
OssUtilFree(pOssValue);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilGetHugeInteger(
|
||
|
IN unsigned int OssLength,
|
||
|
IN unsigned char *pOssValue,
|
||
|
IN DWORD dwFlags,
|
||
|
OUT PCRYPT_INTEGER_BLOB pInfo,
|
||
|
IN OUT BYTE **ppbExtra,
|
||
|
IN OUT LONG *plRemainExtra
|
||
|
)
|
||
|
{
|
||
|
// Since bytes need to be reversed, always need to do a copy (dwFlags = 0)
|
||
|
OssUtilGetOctetString(OssLength, pOssValue, 0,
|
||
|
pInfo, ppbExtra, plRemainExtra);
|
||
|
if (*plRemainExtra >= 0 && pInfo->cbData > 0)
|
||
|
OssUtilReverseBytes(pInfo->pbData, pInfo->cbData);
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Set/Free/Get Huge Unsigned Integer
|
||
|
//
|
||
|
// Set inserts a leading 0x00 before reversing. Note, any extra leading
|
||
|
// 0x00's are removed by OSS before ASN.1 encoding.
|
||
|
//
|
||
|
// Get removes a leading 0x00 if present, after reversing.
|
||
|
//
|
||
|
// OssUtilFreeHugeUINT must be called to free the allocated OssValue.
|
||
|
// OssUtilFreeHugeUINT has been #define'd to OssUtilFreeHugeInteger.
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
OssUtilSetHugeUINT(
|
||
|
IN PCRYPT_UINT_BLOB pInfo,
|
||
|
OUT unsigned int *pOssLength,
|
||
|
OUT unsigned char **ppOssValue
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
DWORD cb = pInfo->cbData;
|
||
|
BYTE *pb;
|
||
|
DWORD i;
|
||
|
|
||
|
if (cb > 0) {
|
||
|
if (NULL == (pb = (BYTE *) OssUtilAlloc(cb + 1)))
|
||
|
goto ErrorReturn;
|
||
|
*pb = 0x00;
|
||
|
for (i = 0; i < cb; i++)
|
||
|
pb[1 + i] = pInfo->pbData[cb - 1 - i];
|
||
|
cb++;
|
||
|
} else
|
||
|
pb = NULL;
|
||
|
fResult = TRUE;
|
||
|
CommonReturn:
|
||
|
*pOssLength = cb;
|
||
|
*ppOssValue = pb;
|
||
|
return fResult;
|
||
|
ErrorReturn:
|
||
|
cb = 0;
|
||
|
fResult = FALSE;
|
||
|
goto CommonReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilGetHugeUINT(
|
||
|
IN unsigned int OssLength,
|
||
|
IN unsigned char *pOssValue,
|
||
|
IN DWORD dwFlags,
|
||
|
OUT PCRYPT_UINT_BLOB pInfo,
|
||
|
IN OUT BYTE **ppbExtra,
|
||
|
IN OUT LONG *plRemainExtra
|
||
|
)
|
||
|
{
|
||
|
// Check for and advance past a leading 0x00.
|
||
|
if (OssLength > 1 && *pOssValue == 0) {
|
||
|
pOssValue++;
|
||
|
OssLength--;
|
||
|
}
|
||
|
OssUtilGetHugeInteger(
|
||
|
OssLength,
|
||
|
pOssValue,
|
||
|
dwFlags,
|
||
|
pInfo,
|
||
|
ppbExtra,
|
||
|
plRemainExtra
|
||
|
);
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Set/Get BitString
|
||
|
//--------------------------------------------------------------------------
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilSetBitString(
|
||
|
IN PCRYPT_BIT_BLOB pInfo,
|
||
|
OUT unsigned int *pOssBitLength,
|
||
|
OUT unsigned char **ppOssValue
|
||
|
)
|
||
|
{
|
||
|
if (pInfo->cbData) {
|
||
|
*ppOssValue = pInfo->pbData;
|
||
|
assert(pInfo->cUnusedBits <= 7);
|
||
|
*pOssBitLength = pInfo->cbData * 8 - pInfo->cUnusedBits;
|
||
|
} else {
|
||
|
*ppOssValue = NULL;
|
||
|
*pOssBitLength = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static const BYTE rgbUnusedAndMask[8] =
|
||
|
{0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
|
||
|
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilGetBitString(
|
||
|
IN unsigned int OssBitLength,
|
||
|
IN unsigned char *pOssValue,
|
||
|
IN DWORD dwFlags,
|
||
|
OUT PCRYPT_BIT_BLOB pInfo,
|
||
|
IN OUT BYTE **ppbExtra,
|
||
|
IN OUT LONG *plRemainExtra
|
||
|
)
|
||
|
{
|
||
|
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG && 0 == (OssBitLength % 8)) {
|
||
|
if (*plRemainExtra >= 0) {
|
||
|
pInfo->cbData = OssBitLength / 8;
|
||
|
pInfo->cUnusedBits = 0;
|
||
|
pInfo->pbData = pOssValue;
|
||
|
}
|
||
|
} else {
|
||
|
LONG lRemainExtra = *plRemainExtra;
|
||
|
BYTE *pbExtra = *ppbExtra;
|
||
|
LONG lAlignExtra;
|
||
|
LONG lData;
|
||
|
DWORD cUnusedBits;
|
||
|
|
||
|
lData = (LONG) OssBitLength / 8;
|
||
|
cUnusedBits = OssBitLength % 8;
|
||
|
if (cUnusedBits) {
|
||
|
cUnusedBits = 8 - cUnusedBits;
|
||
|
lData++;
|
||
|
}
|
||
|
lAlignExtra = INFO_LEN_ALIGN(lData);
|
||
|
lRemainExtra -= lAlignExtra;
|
||
|
if (lRemainExtra >= 0) {
|
||
|
if (lData > 0) {
|
||
|
pInfo->pbData = pbExtra;
|
||
|
pInfo->cbData = (DWORD) lData;
|
||
|
pInfo->cUnusedBits = cUnusedBits;
|
||
|
memcpy(pbExtra, pOssValue, lData);
|
||
|
if (cUnusedBits)
|
||
|
*(pbExtra + lData - 1) &= rgbUnusedAndMask[cUnusedBits];
|
||
|
} else
|
||
|
memset(pInfo, 0, sizeof(*pInfo));
|
||
|
pbExtra += lAlignExtra;
|
||
|
}
|
||
|
*plRemainExtra = lRemainExtra;
|
||
|
*ppbExtra = pbExtra;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Set BitString Without Trailing Zeroes
|
||
|
//--------------------------------------------------------------------------
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilSetBitStringWithoutTrailingZeroes(
|
||
|
IN PCRYPT_BIT_BLOB pInfo,
|
||
|
OUT unsigned int *pOssBitLength,
|
||
|
OUT unsigned char **ppOssValue
|
||
|
)
|
||
|
{
|
||
|
DWORD cbData;
|
||
|
DWORD cUnusedBits;
|
||
|
|
||
|
cbData = pInfo->cbData;
|
||
|
cUnusedBits = pInfo->cUnusedBits;
|
||
|
assert(cUnusedBits <= 7);
|
||
|
|
||
|
if (cbData) {
|
||
|
BYTE *pb;
|
||
|
|
||
|
// Until we find a nonzero byte (starting with the last byte),
|
||
|
// decrement cbData. For the last byte don't look at any unused bits.
|
||
|
pb = pInfo->pbData + cbData - 1;
|
||
|
if (0 == (*pb & rgbUnusedAndMask[cUnusedBits])) {
|
||
|
cUnusedBits = 0;
|
||
|
cbData--;
|
||
|
pb--;
|
||
|
|
||
|
for ( ; 0 < cbData && 0 == *pb; cbData--, pb--)
|
||
|
;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cbData) {
|
||
|
BYTE b;
|
||
|
|
||
|
// Determine the number of unused bits in the last byte. Treat any
|
||
|
// trailing zeroes as unused.
|
||
|
b = *(pInfo->pbData + cbData - 1);
|
||
|
assert(b);
|
||
|
if (cUnusedBits)
|
||
|
b = b >> cUnusedBits;
|
||
|
|
||
|
for (; 7 > cUnusedBits && 0 == (b & 0x01); cUnusedBits++) {
|
||
|
b = b >> 1;
|
||
|
}
|
||
|
assert(b & 0x01);
|
||
|
assert(cUnusedBits <= 7);
|
||
|
|
||
|
*ppOssValue = pInfo->pbData;
|
||
|
*pOssBitLength = cbData * 8 - cUnusedBits;
|
||
|
} else {
|
||
|
*ppOssValue = NULL;
|
||
|
*pOssBitLength = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Get IA5 String
|
||
|
//--------------------------------------------------------------------------
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilGetIA5String(
|
||
|
IN unsigned int OssLength,
|
||
|
IN char *pOssValue,
|
||
|
IN DWORD dwFlags,
|
||
|
OUT LPSTR *ppsz,
|
||
|
IN OUT BYTE **ppbExtra,
|
||
|
IN OUT LONG *plRemainExtra
|
||
|
)
|
||
|
{
|
||
|
LONG lRemainExtra = *plRemainExtra;
|
||
|
BYTE *pbExtra = *ppbExtra;
|
||
|
LONG lAlignExtra;
|
||
|
LONG lData;
|
||
|
|
||
|
lData = (LONG) OssLength;
|
||
|
lAlignExtra = INFO_LEN_ALIGN(lData + 1);
|
||
|
lRemainExtra -= lAlignExtra;
|
||
|
if (lRemainExtra >= 0) {
|
||
|
if (lData > 0)
|
||
|
memcpy(pbExtra, pOssValue, lData);
|
||
|
*(pbExtra + lData) = 0;
|
||
|
*ppsz = (LPSTR) pbExtra;
|
||
|
pbExtra += lAlignExtra;
|
||
|
}
|
||
|
*plRemainExtra = lRemainExtra;
|
||
|
*ppbExtra = pbExtra;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Set/Free/Get Unicode mapped to IA5 String
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
OssUtilSetUnicodeConvertedToIA5String(
|
||
|
IN LPWSTR pwsz,
|
||
|
OUT unsigned int *pOssLength,
|
||
|
OUT char **ppOssValue
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
LPSTR psz = NULL;
|
||
|
int cchUTF8;
|
||
|
int cchWideChar;
|
||
|
int i;
|
||
|
|
||
|
cchWideChar = wcslen(pwsz);
|
||
|
if (cchWideChar == 0) {
|
||
|
*pOssLength = 0;
|
||
|
*ppOssValue = 0;
|
||
|
return TRUE;
|
||
|
}
|
||
|
// Check that the input string contains valid IA5 characters
|
||
|
for (i = 0; i < cchWideChar; i++) {
|
||
|
if (pwsz[i] > 0x7F) {
|
||
|
SetLastError((DWORD) CRYPT_E_INVALID_IA5_STRING);
|
||
|
*pOssLength = (unsigned int) i;
|
||
|
goto InvalidIA5;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cchUTF8 = WideCharToUTF8(
|
||
|
pwsz,
|
||
|
cchWideChar,
|
||
|
NULL, // lpUTF8Str
|
||
|
0 // cchUTF8
|
||
|
);
|
||
|
|
||
|
if (cchUTF8 <= 0)
|
||
|
goto ErrorReturn;
|
||
|
if (NULL == (psz = (LPSTR) OssUtilAlloc(cchUTF8)))
|
||
|
goto ErrorReturn;
|
||
|
cchUTF8 = WideCharToUTF8(
|
||
|
pwsz,
|
||
|
cchWideChar,
|
||
|
psz,
|
||
|
cchUTF8
|
||
|
);
|
||
|
*ppOssValue = psz;
|
||
|
*pOssLength = cchUTF8;
|
||
|
fResult = TRUE;
|
||
|
goto CommonReturn;
|
||
|
|
||
|
ErrorReturn:
|
||
|
*pOssLength = 0;
|
||
|
InvalidIA5:
|
||
|
*ppOssValue = NULL;
|
||
|
fResult = FALSE;
|
||
|
CommonReturn:
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilFreeUnicodeConvertedToIA5String(
|
||
|
IN char *pOssValue
|
||
|
)
|
||
|
{
|
||
|
OssUtilFree(pOssValue);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilGetIA5StringConvertedToUnicode(
|
||
|
IN unsigned int OssLength,
|
||
|
IN char *pOssValue,
|
||
|
IN DWORD dwFlags,
|
||
|
OUT LPWSTR *ppwsz,
|
||
|
IN OUT BYTE **ppbExtra,
|
||
|
IN OUT LONG *plRemainExtra
|
||
|
)
|
||
|
{
|
||
|
LONG lRemainExtra = *plRemainExtra;
|
||
|
BYTE *pbExtra = *ppbExtra;
|
||
|
LONG lAlignExtra;
|
||
|
LONG lData;
|
||
|
int cchWideChar;
|
||
|
|
||
|
cchWideChar = UTF8ToWideChar(
|
||
|
(LPSTR) pOssValue,
|
||
|
OssLength,
|
||
|
NULL, // lpWideCharStr
|
||
|
0 // cchWideChar
|
||
|
);
|
||
|
if (cchWideChar > 0)
|
||
|
lData = cchWideChar * sizeof(WCHAR);
|
||
|
else
|
||
|
lData = 0;
|
||
|
lAlignExtra = INFO_LEN_ALIGN(lData + sizeof(WCHAR));
|
||
|
lRemainExtra -= lAlignExtra;
|
||
|
if (lRemainExtra >= 0) {
|
||
|
if (lData > 0)
|
||
|
UTF8ToWideChar(pOssValue, OssLength,
|
||
|
(LPWSTR) pbExtra, cchWideChar);
|
||
|
memset(pbExtra + lData, 0, sizeof(WCHAR));
|
||
|
*ppwsz = (LPWSTR) pbExtra;
|
||
|
pbExtra += lAlignExtra;
|
||
|
}
|
||
|
*plRemainExtra = lRemainExtra;
|
||
|
*ppbExtra = pbExtra;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Get BMP String
|
||
|
//--------------------------------------------------------------------------
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilGetBMPString(
|
||
|
IN unsigned int OssLength,
|
||
|
IN unsigned short *pOssValue,
|
||
|
IN DWORD dwFlags,
|
||
|
OUT LPWSTR *ppwsz,
|
||
|
IN OUT BYTE **ppbExtra,
|
||
|
IN OUT LONG *plRemainExtra
|
||
|
)
|
||
|
{
|
||
|
LONG lRemainExtra = *plRemainExtra;
|
||
|
BYTE *pbExtra = *ppbExtra;
|
||
|
LONG lAlignExtra;
|
||
|
LONG lData;
|
||
|
|
||
|
lData = (LONG) OssLength * sizeof(WCHAR);
|
||
|
lAlignExtra = INFO_LEN_ALIGN(lData + sizeof(WCHAR));
|
||
|
lRemainExtra -= lAlignExtra;
|
||
|
if (lRemainExtra >= 0) {
|
||
|
if (lData > 0)
|
||
|
memcpy(pbExtra, pOssValue, lData);
|
||
|
memset(pbExtra + lData, 0, sizeof(WCHAR));
|
||
|
*ppwsz = (LPWSTR) pbExtra;
|
||
|
pbExtra += lAlignExtra;
|
||
|
}
|
||
|
*plRemainExtra = lRemainExtra;
|
||
|
*ppbExtra = pbExtra;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Set/Get "Any" DER BLOB
|
||
|
//--------------------------------------------------------------------------
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilSetAny(
|
||
|
IN PCRYPT_OBJID_BLOB pInfo,
|
||
|
OUT OpenType *pOss
|
||
|
)
|
||
|
{
|
||
|
memset(pOss, 0, sizeof(*pOss));
|
||
|
pOss->encoded = pInfo->pbData;
|
||
|
pOss->length = pInfo->cbData;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilGetAny(
|
||
|
IN OpenType *pOss,
|
||
|
IN DWORD dwFlags,
|
||
|
OUT PCRYPT_OBJID_BLOB pInfo,
|
||
|
IN OUT BYTE **ppbExtra,
|
||
|
IN OUT LONG *plRemainExtra
|
||
|
)
|
||
|
{
|
||
|
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) {
|
||
|
if (*plRemainExtra >= 0) {
|
||
|
pInfo->cbData = pOss->length;
|
||
|
pInfo->pbData = (BYTE *) pOss->encoded;
|
||
|
}
|
||
|
} else {
|
||
|
LONG lRemainExtra = *plRemainExtra;
|
||
|
BYTE *pbExtra = *ppbExtra;
|
||
|
LONG lAlignExtra;
|
||
|
LONG lData;
|
||
|
|
||
|
lData = (LONG) pOss->length;
|
||
|
lAlignExtra = INFO_LEN_ALIGN(lData);
|
||
|
lRemainExtra -= lAlignExtra;
|
||
|
if (lRemainExtra >= 0) {
|
||
|
if (lData > 0) {
|
||
|
pInfo->pbData = pbExtra;
|
||
|
pInfo->cbData = (DWORD) lData;
|
||
|
memcpy(pbExtra, pOss->encoded, lData);
|
||
|
} else
|
||
|
memset(pInfo, 0, sizeof(*pInfo));
|
||
|
pbExtra += lAlignExtra;
|
||
|
}
|
||
|
*plRemainExtra = lRemainExtra;
|
||
|
*ppbExtra = pbExtra;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Encode an OSS formatted info structure.
|
||
|
//
|
||
|
// If CRYPT_ENCODE_ALLOC_FLAG is set, allocate memory for pbEncoded and
|
||
|
// return *((BYTE **) pvEncoded) = pbAllocEncoded. Otherwise,
|
||
|
// pvEncoded points to byte array to be updated.
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
OssUtilEncodeInfoEx(
|
||
|
IN OssGlobal *Pog,
|
||
|
IN int pdunum,
|
||
|
IN void *pvOssInfo,
|
||
|
IN DWORD dwFlags,
|
||
|
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
|
||
|
OUT OPTIONAL void *pvEncoded,
|
||
|
IN OUT DWORD *pcbEncoded
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
DWORD cbEncoded;
|
||
|
OssBuf OssEncoded;
|
||
|
int OssStatus;
|
||
|
unsigned char *value;
|
||
|
|
||
|
if (NULL == pvEncoded || (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
|
||
|
cbEncoded = 0;
|
||
|
else
|
||
|
cbEncoded = *pcbEncoded;
|
||
|
|
||
|
OssEncoded.length = cbEncoded;
|
||
|
if (cbEncoded == 0)
|
||
|
value = NULL;
|
||
|
else
|
||
|
value = (unsigned char *) pvEncoded;
|
||
|
OssEncoded.value = value;
|
||
|
|
||
|
ossSetEncodingRules(Pog, OSS_DER);
|
||
|
OssStatus = ossEncode(
|
||
|
Pog,
|
||
|
pdunum,
|
||
|
pvOssInfo,
|
||
|
&OssEncoded);
|
||
|
cbEncoded = OssEncoded.length;
|
||
|
|
||
|
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
|
||
|
PFN_CRYPT_ALLOC pfnAlloc;
|
||
|
BYTE *pbEncoded;
|
||
|
|
||
|
if (0 != OssStatus || 0 == cbEncoded) {
|
||
|
ossFreeBuf(Pog, OssEncoded.value);
|
||
|
*((void **) pvEncoded) = NULL;
|
||
|
goto OssError;
|
||
|
}
|
||
|
|
||
|
pfnAlloc = PkiGetEncodeAllocFunction(pEncodePara);
|
||
|
if (NULL == (pbEncoded = (BYTE *) pfnAlloc(cbEncoded))) {
|
||
|
ossFreeBuf(Pog, OssEncoded.value);
|
||
|
*((void **) pvEncoded) = NULL;
|
||
|
goto OutOfMemory;
|
||
|
}
|
||
|
memcpy(pbEncoded, OssEncoded.value, cbEncoded);
|
||
|
*((BYTE **) pvEncoded) = pbEncoded;
|
||
|
ossFreeBuf(Pog, OssEncoded.value);
|
||
|
goto SuccessReturn;
|
||
|
} else if (value == NULL && OssEncoded.value) {
|
||
|
// Length only calculation with a throw away allocation
|
||
|
ossFreeBuf(Pog, OssEncoded.value);
|
||
|
if (pvEncoded && 0 == OssStatus) {
|
||
|
// Upon entry *pcbEncoded == 0
|
||
|
goto LengthError;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (0 != OssStatus) {
|
||
|
// For MORE_BUF:: redo as a length only calculation
|
||
|
if (OssStatus == MORE_BUF && pvEncoded &&
|
||
|
OssUtilEncodeInfoEx(
|
||
|
Pog,
|
||
|
pdunum,
|
||
|
pvOssInfo,
|
||
|
0, // dwFlags
|
||
|
NULL, // pEncodePara
|
||
|
NULL, // pbEncoded
|
||
|
&cbEncoded))
|
||
|
goto LengthError;
|
||
|
else {
|
||
|
cbEncoded = 0;
|
||
|
goto OssError;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SuccessReturn:
|
||
|
fResult = TRUE;
|
||
|
CommonReturn:
|
||
|
*pcbEncoded = cbEncoded;
|
||
|
return fResult;
|
||
|
|
||
|
ErrorReturn:
|
||
|
fResult = FALSE;
|
||
|
goto CommonReturn;
|
||
|
TRACE_ERROR(OutOfMemory)
|
||
|
SET_ERROR(LengthError, ERROR_MORE_DATA)
|
||
|
SET_ERROR_VAR(OssError, CRYPT_E_OSS_ERROR + OssStatus)
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Encode an OSS formatted info structure
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
OssUtilEncodeInfo(
|
||
|
IN OssGlobal *Pog,
|
||
|
IN int pdunum,
|
||
|
IN void *pvOssInfo,
|
||
|
OUT OPTIONAL BYTE *pbEncoded,
|
||
|
IN OUT DWORD *pcbEncoded
|
||
|
)
|
||
|
{
|
||
|
return OssUtilEncodeInfoEx(
|
||
|
Pog,
|
||
|
pdunum,
|
||
|
pvOssInfo,
|
||
|
0, // dwFlags
|
||
|
NULL, // pEncodePara
|
||
|
pbEncoded,
|
||
|
pcbEncoded
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Decode into an allocated, OSS formatted info structure
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
OssUtilDecodeAndAllocInfo(
|
||
|
IN OssGlobal *Pog,
|
||
|
IN int pdunum,
|
||
|
IN const BYTE *pbEncoded,
|
||
|
IN DWORD cbEncoded,
|
||
|
OUT void **ppvOssInfo
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
OssBuf OssEncoded;
|
||
|
int OssStatus;
|
||
|
|
||
|
OssEncoded.length = cbEncoded;
|
||
|
OssEncoded.value = (unsigned char *) pbEncoded;
|
||
|
|
||
|
ossSetEncodingRules(Pog, OSS_BER);
|
||
|
*ppvOssInfo = NULL;
|
||
|
if (0 != (OssStatus = ossDecode(
|
||
|
Pog,
|
||
|
&pdunum,
|
||
|
&OssEncoded,
|
||
|
ppvOssInfo)))
|
||
|
goto OssError;
|
||
|
fResult = TRUE;
|
||
|
CommonReturn:
|
||
|
return fResult;
|
||
|
|
||
|
ErrorReturn:
|
||
|
*ppvOssInfo = NULL;
|
||
|
fResult = FALSE;
|
||
|
goto CommonReturn;
|
||
|
SET_ERROR_VAR(OssError, CRYPT_E_OSS_ERROR + OssStatus)
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Free an allocated, OSS formatted info structure
|
||
|
//--------------------------------------------------------------------------
|
||
|
void
|
||
|
WINAPI
|
||
|
OssUtilFreeInfo(
|
||
|
IN OssGlobal *Pog,
|
||
|
IN int pdunum,
|
||
|
IN void *pvOssInfo
|
||
|
)
|
||
|
{
|
||
|
if (pvOssInfo) {
|
||
|
ossFreePDU(Pog, pdunum, pvOssInfo);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Call the callback to convert the OSS structure into the 'C' structure.
|
||
|
// If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
|
||
|
// structure and call the callback initially to get the length and then
|
||
|
// a second time to update the allocated 'C' structure.
|
||
|
//
|
||
|
// Allocated structure is returned:
|
||
|
// *((void **) pvStructInfo) = pvAllocStructInfo
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
OssUtilAllocStructInfoEx(
|
||
|
IN void *pvOssInfo,
|
||
|
IN DWORD dwFlags,
|
||
|
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
|
||
|
IN PFN_OSS_UTIL_DECODE_EX_CALLBACK pfnDecodeExCallback,
|
||
|
OUT OPTIONAL void *pvStructInfo,
|
||
|
IN OUT DWORD *pcbStructInfo
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
LONG lRemainExtra;
|
||
|
DWORD cbStructInfo;
|
||
|
|
||
|
if (NULL == pvStructInfo || (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) {
|
||
|
cbStructInfo = 0;
|
||
|
lRemainExtra = 0;
|
||
|
} else {
|
||
|
cbStructInfo = *pcbStructInfo;
|
||
|
lRemainExtra = (LONG) cbStructInfo;
|
||
|
}
|
||
|
|
||
|
if (!pfnDecodeExCallback(
|
||
|
pvOssInfo,
|
||
|
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
|
||
|
pDecodePara,
|
||
|
pvStructInfo,
|
||
|
&lRemainExtra
|
||
|
)) goto DecodeCallbackError;
|
||
|
|
||
|
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) {
|
||
|
void *pv;
|
||
|
PFN_CRYPT_ALLOC pfnAlloc = PkiGetDecodeAllocFunction(pDecodePara);
|
||
|
|
||
|
assert(0 > lRemainExtra);
|
||
|
lRemainExtra = -lRemainExtra;
|
||
|
cbStructInfo = (DWORD) lRemainExtra;
|
||
|
|
||
|
if (NULL == (pv = pfnAlloc(cbStructInfo)))
|
||
|
goto OutOfMemory;
|
||
|
if (!pfnDecodeExCallback(
|
||
|
pvOssInfo,
|
||
|
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
|
||
|
pDecodePara,
|
||
|
pv,
|
||
|
&lRemainExtra
|
||
|
)) {
|
||
|
PFN_CRYPT_FREE pfnFree = PkiGetDecodeFreeFunction(pDecodePara);
|
||
|
pfnFree(pv);
|
||
|
goto DecodeCallbackError;
|
||
|
}
|
||
|
*((void **) pvStructInfo) = pv;
|
||
|
assert(0 <= lRemainExtra);
|
||
|
}
|
||
|
|
||
|
if (0 <= lRemainExtra) {
|
||
|
cbStructInfo = cbStructInfo - (DWORD) lRemainExtra;
|
||
|
} else {
|
||
|
cbStructInfo = cbStructInfo + (DWORD) -lRemainExtra;
|
||
|
if (pvStructInfo) {
|
||
|
SetLastError((DWORD) ERROR_MORE_DATA);
|
||
|
fResult = FALSE;
|
||
|
goto CommonReturn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fResult = TRUE;
|
||
|
CommonReturn:
|
||
|
*pcbStructInfo = cbStructInfo;
|
||
|
return fResult;
|
||
|
|
||
|
ErrorReturn:
|
||
|
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
||
|
*((void **) pvStructInfo) = NULL;
|
||
|
cbStructInfo = 0;
|
||
|
fResult = FALSE;
|
||
|
goto CommonReturn;
|
||
|
TRACE_ERROR(DecodeCallbackError)
|
||
|
TRACE_ERROR(OutOfMemory)
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Decode the OSS formatted info structure and call the callback
|
||
|
// function to convert the OSS structure to the 'C' structure.
|
||
|
//
|
||
|
// If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
|
||
|
// structure and call the callback initially to get the length and then
|
||
|
// a second time to update the allocated 'C' structure.
|
||
|
//
|
||
|
// Allocated structure is returned:
|
||
|
// *((void **) pvStructInfo) = pvAllocStructInfo
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
OssUtilDecodeAndAllocInfoEx(
|
||
|
IN OssGlobal *Pog,
|
||
|
IN int pdunum,
|
||
|
IN const BYTE *pbEncoded,
|
||
|
IN DWORD cbEncoded,
|
||
|
IN DWORD dwFlags,
|
||
|
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
|
||
|
IN PFN_OSS_UTIL_DECODE_EX_CALLBACK pfnDecodeExCallback,
|
||
|
OUT OPTIONAL void *pvStructInfo,
|
||
|
IN OUT DWORD *pcbStructInfo
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
void *pvOssInfo = NULL;
|
||
|
|
||
|
if (!OssUtilDecodeAndAllocInfo(
|
||
|
Pog,
|
||
|
pdunum,
|
||
|
pbEncoded,
|
||
|
cbEncoded,
|
||
|
&pvOssInfo
|
||
|
)) goto OssDecodeError;
|
||
|
|
||
|
fResult = OssUtilAllocStructInfoEx(
|
||
|
pvOssInfo,
|
||
|
dwFlags,
|
||
|
pDecodePara,
|
||
|
pfnDecodeExCallback,
|
||
|
pvStructInfo,
|
||
|
pcbStructInfo
|
||
|
);
|
||
|
CommonReturn:
|
||
|
OssUtilFreeInfo(Pog, pdunum, pvOssInfo);
|
||
|
return fResult;
|
||
|
|
||
|
ErrorReturn:
|
||
|
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
||
|
*((void **) pvStructInfo) = NULL;
|
||
|
*pcbStructInfo = 0;
|
||
|
fResult = FALSE;
|
||
|
goto CommonReturn;
|
||
|
TRACE_ERROR(OssDecodeError)
|
||
|
}
|