You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
694 lines
18 KiB
694 lines
18 KiB
//+-------------------------------------------------------------------------
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1998
|
|
//
|
|
// File: pkiasn1.cpp
|
|
//
|
|
// Contents: PKI ASN.1 support functions.
|
|
//
|
|
// Functions: PkiAsn1Encode
|
|
// PkiAsn1Decode
|
|
// PkiAsn1SetEncodingRule
|
|
// PkiAsn1GetEncodingRule
|
|
//
|
|
// PkiAsn1ReverseBytes
|
|
// PkiAsn1EncodeInfoEx
|
|
// PkiAsn1EncodeInfo
|
|
// PkiAsn1DecodeAndAllocInfo
|
|
// PkiAsn1AllocStructInfoEx
|
|
// PkiAsn1DecodeAndAllocInfoEx
|
|
//
|
|
// PkiAsn1ToObjectIdentifier
|
|
// PkiAsn1FromObjectIdentifier
|
|
//
|
|
//
|
|
// History: 23-Oct-98 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)
|
|
|
|
|
|
inline BOOL my_isdigit( char ch)
|
|
{
|
|
return (ch >= '0') && (ch <= '9');
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Asn1 Encode function. The encoded output is allocated and must be freed
|
|
// by calling PkiAsn1FreeEncoded().
|
|
//--------------------------------------------------------------------------
|
|
ASN1error_e
|
|
WINAPI
|
|
PkiAsn1Encode(
|
|
IN ASN1encoding_t pEnc,
|
|
IN void *pvAsn1Info,
|
|
IN ASN1uint32_t id,
|
|
OUT BYTE **ppbEncoded,
|
|
OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
ASN1error_e Asn1Err;
|
|
|
|
Asn1Err = ASN1_Encode(
|
|
pEnc,
|
|
pvAsn1Info,
|
|
id,
|
|
ASN1ENCODE_ALLOCATEBUFFER,
|
|
NULL, // pbBuf
|
|
0 // cbBufSize
|
|
);
|
|
|
|
if (ASN1_SUCCEEDED(Asn1Err)) {
|
|
Asn1Err = ASN1_SUCCESS;
|
|
*ppbEncoded = pEnc->buf;
|
|
*pcbEncoded = pEnc->len;
|
|
} else {
|
|
*ppbEncoded = NULL;
|
|
*pcbEncoded = 0;
|
|
}
|
|
return Asn1Err;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Asn1 Encode function. The encoded output isn't allocated.
|
|
//
|
|
// If pbEncoded is NULL, does a length only calculation.
|
|
//--------------------------------------------------------------------------
|
|
ASN1error_e
|
|
WINAPI
|
|
PkiAsn1Encode2(
|
|
IN ASN1encoding_t pEnc,
|
|
IN void *pvAsn1Info,
|
|
IN ASN1uint32_t id,
|
|
OUT OPTIONAL BYTE *pbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
ASN1error_e Asn1Err;
|
|
DWORD cbEncoded;
|
|
|
|
if (NULL == pbEncoded)
|
|
cbEncoded = 0;
|
|
else
|
|
cbEncoded = *pcbEncoded;
|
|
|
|
if (0 == cbEncoded) {
|
|
// Length only calculation
|
|
|
|
Asn1Err = ASN1_Encode(
|
|
pEnc,
|
|
pvAsn1Info,
|
|
id,
|
|
ASN1ENCODE_ALLOCATEBUFFER,
|
|
NULL, // pbBuf
|
|
0 // cbBufSize
|
|
);
|
|
|
|
if (ASN1_SUCCEEDED(Asn1Err)) {
|
|
if (pbEncoded)
|
|
Asn1Err = ASN1_ERR_OVERFLOW;
|
|
else
|
|
Asn1Err = ASN1_SUCCESS;
|
|
cbEncoded = pEnc->len;
|
|
PkiAsn1FreeEncoded(pEnc, pEnc->buf);
|
|
}
|
|
} else {
|
|
Asn1Err = ASN1_Encode(
|
|
pEnc,
|
|
pvAsn1Info,
|
|
id,
|
|
ASN1ENCODE_SETBUFFER,
|
|
pbEncoded,
|
|
cbEncoded
|
|
);
|
|
|
|
if (ASN1_SUCCEEDED(Asn1Err)) {
|
|
Asn1Err = ASN1_SUCCESS;
|
|
cbEncoded = pEnc->len;
|
|
} else if (ASN1_ERR_OVERFLOW == Asn1Err) {
|
|
// Re-do as length only calculation
|
|
Asn1Err = PkiAsn1Encode2(
|
|
pEnc,
|
|
pvAsn1Info,
|
|
id,
|
|
NULL, // pbEncoded
|
|
&cbEncoded
|
|
);
|
|
if (ASN1_SUCCESS == Asn1Err)
|
|
Asn1Err = ASN1_ERR_OVERFLOW;
|
|
} else
|
|
cbEncoded = 0;
|
|
}
|
|
|
|
*pcbEncoded = cbEncoded;
|
|
return Asn1Err;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Asn1 Decode function. The allocated, decoded structure, **pvAsn1Info, must
|
|
// be freed by calling PkiAsn1FreeDecoded().
|
|
//--------------------------------------------------------------------------
|
|
ASN1error_e
|
|
WINAPI
|
|
PkiAsn1Decode(
|
|
IN ASN1decoding_t pDec,
|
|
OUT void **ppvAsn1Info,
|
|
IN ASN1uint32_t id,
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded
|
|
)
|
|
{
|
|
ASN1error_e Asn1Err;
|
|
|
|
*ppvAsn1Info = NULL;
|
|
Asn1Err = ASN1_Decode(
|
|
pDec,
|
|
ppvAsn1Info,
|
|
id,
|
|
ASN1DECODE_SETBUFFER,
|
|
(BYTE *) pbEncoded,
|
|
cbEncoded
|
|
);
|
|
if (ASN1_SUCCEEDED(Asn1Err))
|
|
Asn1Err = ASN1_SUCCESS;
|
|
else {
|
|
if (ASN1_ERR_BADARGS == Asn1Err)
|
|
Asn1Err = ASN1_ERR_EOD;
|
|
*ppvAsn1Info = NULL;
|
|
}
|
|
return Asn1Err;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Asn1 Decode function. The allocated, decoded structure, **pvAsn1Info, must
|
|
// be freed by calling PkiAsn1FreeDecoded().
|
|
//
|
|
// For a successful decode, *ppbEncoded is advanced
|
|
// past the decoded bytes and *pcbDecoded is decremented by the number
|
|
// of decoded bytes.
|
|
//--------------------------------------------------------------------------
|
|
ASN1error_e
|
|
WINAPI
|
|
PkiAsn1Decode2(
|
|
IN ASN1decoding_t pDec,
|
|
OUT void **ppvAsn1Info,
|
|
IN ASN1uint32_t id,
|
|
IN OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
ASN1error_e Asn1Err;
|
|
|
|
*ppvAsn1Info = NULL;
|
|
Asn1Err = ASN1_Decode(
|
|
pDec,
|
|
ppvAsn1Info,
|
|
id,
|
|
ASN1DECODE_SETBUFFER,
|
|
*ppbEncoded,
|
|
*pcbEncoded
|
|
);
|
|
if (ASN1_SUCCEEDED(Asn1Err)) {
|
|
Asn1Err = ASN1_SUCCESS;
|
|
*ppbEncoded += pDec->len;
|
|
*pcbEncoded -= pDec->len;
|
|
} else {
|
|
if (ASN1_ERR_BADARGS == Asn1Err)
|
|
Asn1Err = ASN1_ERR_EOD;
|
|
*ppvAsn1Info = NULL;
|
|
}
|
|
return Asn1Err;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Asn1 Set/Get encoding rules functions
|
|
//--------------------------------------------------------------------------
|
|
ASN1error_e
|
|
WINAPI
|
|
PkiAsn1SetEncodingRule(
|
|
IN ASN1encoding_t pEnc,
|
|
IN ASN1encodingrule_e eRule
|
|
)
|
|
{
|
|
ASN1optionparam_s OptParam;
|
|
|
|
OptParam.eOption = ASN1OPT_CHANGE_RULE;
|
|
OptParam.eRule = eRule;
|
|
|
|
return ASN1_SetEncoderOption(pEnc, &OptParam);
|
|
}
|
|
|
|
ASN1encodingrule_e
|
|
WINAPI
|
|
PkiAsn1GetEncodingRule(
|
|
IN ASN1encoding_t pEnc
|
|
)
|
|
{
|
|
ASN1error_e Asn1Err;
|
|
ASN1encodingrule_e eRule;
|
|
ASN1optionparam_s OptParam;
|
|
OptParam.eOption = ASN1OPT_GET_RULE;
|
|
|
|
Asn1Err = ASN1_GetEncoderOption(pEnc, &OptParam);
|
|
if (ASN1_SUCCEEDED(Asn1Err))
|
|
eRule = OptParam.eRule;
|
|
else
|
|
eRule = ASN1_BER_RULE_DER;
|
|
|
|
return eRule;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Reverses a buffer of bytes in place
|
|
//--------------------------------------------------------------------------
|
|
void
|
|
WINAPI
|
|
PkiAsn1ReverseBytes(
|
|
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;
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Encode an ASN1 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
|
|
PkiAsn1EncodeInfoEx(
|
|
IN ASN1encoding_t pEnc,
|
|
IN ASN1uint32_t id,
|
|
IN void *pvAsn1Info,
|
|
IN DWORD dwFlags,
|
|
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
|
|
OUT OPTIONAL void *pvEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
ASN1error_e Asn1Err;
|
|
DWORD cbEncoded;
|
|
|
|
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
|
|
BYTE *pbEncoded;
|
|
BYTE *pbAllocEncoded;
|
|
PFN_CRYPT_ALLOC pfnAlloc;
|
|
|
|
PkiAsn1SetEncodingRule(pEnc, ASN1_BER_RULE_DER);
|
|
Asn1Err = PkiAsn1Encode(
|
|
pEnc,
|
|
pvAsn1Info,
|
|
id,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
);
|
|
|
|
if (ASN1_SUCCESS != Asn1Err) {
|
|
*((void **) pvEncoded) = NULL;
|
|
goto Asn1EncodeError;
|
|
}
|
|
|
|
pfnAlloc = PkiGetEncodeAllocFunction(pEncodePara);
|
|
if (NULL == (pbAllocEncoded = (BYTE *) pfnAlloc(cbEncoded))) {
|
|
PkiAsn1FreeEncoded(pEnc, pbEncoded);
|
|
*((void **) pvEncoded) = NULL;
|
|
goto OutOfMemory;
|
|
}
|
|
memcpy(pbAllocEncoded, pbEncoded, cbEncoded);
|
|
*((BYTE **) pvEncoded) = pbAllocEncoded;
|
|
PkiAsn1FreeEncoded(pEnc, pbEncoded);
|
|
} else {
|
|
cbEncoded = *pcbEncoded;
|
|
PkiAsn1SetEncodingRule(pEnc, ASN1_BER_RULE_DER);
|
|
Asn1Err = PkiAsn1Encode2(
|
|
pEnc,
|
|
pvAsn1Info,
|
|
id,
|
|
(BYTE *) pvEncoded,
|
|
&cbEncoded
|
|
);
|
|
|
|
if (ASN1_SUCCESS != Asn1Err) {
|
|
if (ASN1_ERR_OVERFLOW == Asn1Err)
|
|
goto LengthError;
|
|
else
|
|
goto Asn1EncodeError;
|
|
}
|
|
}
|
|
|
|
fResult = TRUE;
|
|
CommonReturn:
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
|
|
ErrorReturn:
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
|
|
OutOfMemory:
|
|
goto ErrorReturn;
|
|
|
|
LengthError:
|
|
SetLastError(ERROR_MORE_DATA);
|
|
goto ErrorReturn;
|
|
|
|
Asn1EncodeError:
|
|
SetLastError(PkiAsn1ErrToHr(Asn1Err));
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Encode an ASN1 formatted info structure
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
PkiAsn1EncodeInfo(
|
|
IN ASN1encoding_t pEnc,
|
|
IN ASN1uint32_t id,
|
|
IN void *pvAsn1Info,
|
|
OUT OPTIONAL BYTE *pbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
return PkiAsn1EncodeInfoEx(
|
|
pEnc,
|
|
id,
|
|
pvAsn1Info,
|
|
0, // dwFlags
|
|
NULL, // pEncodePara
|
|
pbEncoded,
|
|
pcbEncoded
|
|
);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Decode into an allocated, ASN1 formatted info structure
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
PkiAsn1DecodeAndAllocInfo(
|
|
IN ASN1decoding_t pDec,
|
|
IN ASN1uint32_t id,
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
OUT void **ppvAsn1Info
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
ASN1error_e Asn1Err;
|
|
|
|
*ppvAsn1Info = NULL;
|
|
if (ASN1_SUCCESS != (Asn1Err = PkiAsn1Decode(
|
|
pDec,
|
|
ppvAsn1Info,
|
|
id,
|
|
pbEncoded,
|
|
cbEncoded
|
|
)))
|
|
goto Asn1DecodeError;
|
|
fResult = TRUE;
|
|
CommonReturn:
|
|
return fResult;
|
|
|
|
ErrorReturn:
|
|
*ppvAsn1Info = NULL;
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
|
|
Asn1DecodeError:
|
|
SetLastError(PkiAsn1ErrToHr(Asn1Err));
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Call the callback to convert the ASN1 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
|
|
PkiAsn1AllocStructInfoEx(
|
|
IN void *pvAsn1Info,
|
|
IN DWORD dwFlags,
|
|
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
|
|
IN PFN_PKI_ASN1_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(
|
|
pvAsn1Info,
|
|
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(
|
|
pvAsn1Info,
|
|
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;
|
|
|
|
DecodeCallbackError:
|
|
goto ErrorReturn;
|
|
|
|
OutOfMemory:
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Decode the ASN1 formatted info structure and call the callback
|
|
// function to convert the ASN1 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
|
|
PkiAsn1DecodeAndAllocInfoEx(
|
|
IN ASN1decoding_t pDec,
|
|
IN ASN1uint32_t id,
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
IN DWORD dwFlags,
|
|
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
|
|
IN PFN_PKI_ASN1_DECODE_EX_CALLBACK pfnDecodeExCallback,
|
|
OUT OPTIONAL void *pvStructInfo,
|
|
IN OUT DWORD *pcbStructInfo
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
void *pvAsn1Info = NULL;
|
|
|
|
if (!PkiAsn1DecodeAndAllocInfo(
|
|
pDec,
|
|
id,
|
|
pbEncoded,
|
|
cbEncoded,
|
|
&pvAsn1Info
|
|
)) goto Asn1DecodeError;
|
|
|
|
fResult = PkiAsn1AllocStructInfoEx(
|
|
pvAsn1Info,
|
|
dwFlags,
|
|
pDecodePara,
|
|
pfnDecodeExCallback,
|
|
pvStructInfo,
|
|
pcbStructInfo
|
|
);
|
|
CommonReturn:
|
|
PkiAsn1FreeInfo(pDec, id, pvAsn1Info);
|
|
return fResult;
|
|
|
|
ErrorReturn:
|
|
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
|
*((void **) pvStructInfo) = NULL;
|
|
*pcbStructInfo = 0;
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
|
|
Asn1DecodeError:
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert the ascii string ("1.2.9999") to ASN1's Object Identifier
|
|
// represented as an array of unsigned longs.
|
|
//
|
|
// Returns TRUE for a successful conversion.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
PkiAsn1ToObjectIdentifier(
|
|
IN LPCSTR pszObjId,
|
|
IN OUT ASN1uint16_t *pCount,
|
|
OUT ASN1uint32_t rgulValue[]
|
|
)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
unsigned short c = 0;
|
|
LPSTR psz = (LPSTR) pszObjId;
|
|
char ch;
|
|
|
|
if (psz) {
|
|
ASN1uint16_t cMax = *pCount;
|
|
ASN1uint32_t *pul = rgulValue;
|
|
while ((ch = *psz) != '\0' && c++ < cMax) {
|
|
*pul++ = (ASN1uint32_t)atol(psz);
|
|
while (my_isdigit(ch = *psz++))
|
|
;
|
|
if (ch != '.')
|
|
break;
|
|
}
|
|
if (ch != '\0')
|
|
fResult = FALSE;
|
|
}
|
|
*pCount = c;
|
|
return fResult;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Convert from ASN1'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
|
|
PkiAsn1FromObjectIdentifier(
|
|
IN ASN1uint16_t Count,
|
|
IN ASN1uint32_t 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;
|
|
ASN1uint32_t *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;
|
|
}
|