Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2416 lines
70 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: xmsasnx.cpp
//
// Contents:
// Encode/Decode APIs
//
// Implementation using the MS ASN1 compiler / RTS.
//
// Functions: CryptEncodeObject
// CryptDecodeObject
//
// History: 02-Nov-98 philh created
//
//--------------------------------------------------------------------------
//
// ASN1C needs to be defined so that the compiler does not pickup the ASN1 routines from
// the import table
//
#ifdef _X86_
#define ASN1C
#endif
#include "stdafx.h"
#include <windows.h>
#include <wincrypt.h>
#include <malloc.h>
#include "xenroll.h"
#include "cenroll.h"
#pragma warning(disable:4100) // 'var' : unreferenced formal parameter
#include "pkiasn1.h"
#pragma warning(default:4100) // re-enable 4100
#include "pkialloc.h"
#include "crypttls.h"
extern "C"
{
#include "xmsasn.h"
}
#define NO_OSS_DEBUG
#include <dbgdef.h>
// All the *pvInfo extra stuff needs to be aligned
#define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
HCRYPTASN1MODULE hAsn1Module = NULL;
HMODULE hCrypt32Dll = NULL;
typedef HCRYPTASN1MODULE (WINAPI *PFN_CRYPT_INSTALL_ASN1_MODULE) (
IN ASN1module_t pMod,
IN DWORD dwFlags,
IN void *pvReserved
);
typedef BOOL (WINAPI *PFN_CRYPT_UNINSTALL_ASN1_MODULE) (
IN HCRYPTASN1MODULE hAsn1Module
);
typedef ASN1encoding_t (WINAPI *PFN_CRYPT_GET_ASN1_ENCODER)(
IN HCRYPTASN1MODULE hAsn1Module
);
typedef ASN1decoding_t (WINAPI *PFN_CRYPT_GET_ASN1_DECODER)(
IN HCRYPTASN1MODULE hAsn1Module
);
PFN_CRYPT_INSTALL_ASN1_MODULE pfnCryptInstallAsn1Module = NULL;
PFN_CRYPT_UNINSTALL_ASN1_MODULE pfnCryptUninstallAsn1Module = NULL;
PFN_CRYPT_GET_ASN1_ENCODER pfnCryptGetAsn1Encoder = NULL;
PFN_CRYPT_GET_ASN1_DECODER pfnCryptGetAsn1Decoder = NULL;
//+-------------------------------------------------------------------------
// Function: GetEncoder/GetDecoder
//
// Synopsis: Initialize thread local storage for the asn libs
//
// Returns: pointer to an initialized Asn1 encoder/decoder data
// structures
//--------------------------------------------------------------------------
static ASN1encoding_t GetEncoder(void)
{
if (hAsn1Module)
return pfnCryptGetAsn1Encoder(hAsn1Module);
else
return NULL;
}
static ASN1decoding_t GetDecoder(void)
{
if (hAsn1Module)
return pfnCryptGetAsn1Decoder(hAsn1Module);
else
return NULL;
}
//+-------------------------------------------------------------------------
// Cert allocation and free functions
//--------------------------------------------------------------------------
static void *CertAlloc(
IN size_t cbBytes
)
{
void *pv;
pv = malloc(cbBytes);
if (pv == NULL)
SetLastError((DWORD) E_OUTOFMEMORY);
return pv;
}
static void CertFree(
IN void *pv
)
{
free(pv);
}
//+-------------------------------------------------------------------------
// Encode an ASN1 formatted info structure
//
// Called by the Asn1X509*Encode() functions.
//--------------------------------------------------------------------------
static BOOL Asn1InfoEncode(
IN int pdunum,
IN void *pAsn1Info,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
)
{
ASN1encoding_t ge = GetEncoder();
if (NULL == ge)
return FALSE;
return PkiAsn1EncodeInfo(
ge,
pdunum,
pAsn1Info,
pbEncoded,
pcbEncoded);
}
//+-------------------------------------------------------------------------
// Decode into an allocated, ASN1 formatted info structure
//
// Called by the Asn1X509*Decode() functions.
//--------------------------------------------------------------------------
static BOOL Asn1InfoDecodeAndAlloc(
IN int pdunum,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
OUT void **ppAsn1Info
)
{
return PkiAsn1DecodeAndAllocInfo(
GetDecoder(),
pdunum,
pbEncoded,
cbEncoded,
ppAsn1Info);
}
//+-------------------------------------------------------------------------
// Free an allocated, ASN1 formatted info structure
//
// Called by the Asn1X509*Decode() functions.
//--------------------------------------------------------------------------
static void Asn1InfoFree(
IN int pdunum,
IN void *pAsn1Info
)
{
if (pAsn1Info) {
DWORD dwErr = GetLastError();
// TlsGetValue globbers LastError
PkiAsn1FreeInfo(GetDecoder(), pdunum, pAsn1Info);
SetLastError(dwErr);
}
}
//+-------------------------------------------------------------------------
// ASN1 X509 v3 ASN.1 Set / Get functions
//
// Called by the ASN1 X509 encode/decode functions.
//
// Assumption: all types are UNBOUNDED.
//
// 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.
//--------------------------------------------------------------------------
//+-------------------------------------------------------------------------
// Set/Get Object Identifier string
//--------------------------------------------------------------------------
static BOOL Asn1X509SetObjId(
IN LPSTR pszObjId,
OUT ObjectID *pAsn1
)
{
pAsn1->count = sizeof(pAsn1->value) / sizeof(pAsn1->value[0]);
if (PkiAsn1ToObjectIdentifier(pszObjId, &pAsn1->count, pAsn1->value))
return TRUE;
else {
SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
return FALSE;
}
}
static void Asn1X509GetObjId(
IN ObjectID *pAsn1,
IN DWORD /*dwFlags*/,
OUT LPSTR *ppszObjId,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra = *ppbExtra;
LONG lAlignExtra;
DWORD cbObjId;
cbObjId = lRemainExtra > 0 ? lRemainExtra : 0;
PkiAsn1FromObjectIdentifier(
pAsn1->count,
pAsn1->value,
(LPSTR) pbExtra,
&cbObjId
);
lAlignExtra = INFO_LEN_ALIGN(cbObjId);
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
if(cbObjId) {
*ppszObjId = (LPSTR) pbExtra;
} else
*ppszObjId = NULL;
pbExtra += lAlignExtra;
}
*plRemainExtra = lRemainExtra;
*ppbExtra = pbExtra;
}
static BOOL WINAPI Asn1X509CtlUsageEncode(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCTL_USAGE pInfo,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
);
static BOOL WINAPI Asn1X509CtlUsageDecode(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
OUT PCTL_USAGE pInfo,
IN OUT DWORD *pcbInfo
);
static BOOL WINAPI Asn1RequestInfoDecode(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
OUT RequestFlags * pInfo,
IN OUT DWORD *pcbInfo
);
static BOOL WINAPI Asn1RequestInfoEncode(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN RequestFlags * pInfo,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
);
static BOOL WINAPI Asn1CSPProviderEncode(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCRYPT_CSP_PROVIDER pCSPProvider,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
);
static BOOL WINAPI Asn1NameValueEncode(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCRYPT_ENROLLMENT_NAME_VALUE_PAIR pNameValue,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
);
static const CRYPT_OID_FUNC_ENTRY X509EncodeFuncTable[] = {
X509_ENHANCED_KEY_USAGE, Asn1X509CtlUsageEncode,
XENROLL_REQUEST_INFO, Asn1RequestInfoEncode,
szOID_ENROLLMENT_CSP_PROVIDER, Asn1CSPProviderEncode,
szOID_ENROLLMENT_NAME_VALUE_PAIR, Asn1NameValueEncode,
};
#define X509_ENCODE_FUNC_COUNT (sizeof(X509EncodeFuncTable) / \
sizeof(X509EncodeFuncTable[0]))
static const CRYPT_OID_FUNC_ENTRY X509DecodeFuncTable[] = {
X509_ENHANCED_KEY_USAGE, Asn1X509CtlUsageDecode,
XENROLL_REQUEST_INFO, Asn1RequestInfoDecode
};
#define X509_DECODE_FUNC_COUNT (sizeof(X509DecodeFuncTable) / \
sizeof(X509DecodeFuncTable[0]))
//+=========================================================================
// Certificate Management Messages over CMS (CMC) Encode/Decode Functions
//==========================================================================
BOOL WINAPI Asn1CmcDataEncodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCMC_DATA_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
);
BOOL WINAPI Asn1CmcDataDecodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
);
BOOL WINAPI Asn1CmcResponseEncodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCMC_RESPONSE_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
);
BOOL WINAPI Asn1CmcResponseDecodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
);
BOOL WINAPI Asn1CmcStatusEncodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCMC_STATUS_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
);
BOOL WINAPI Asn1CmcStatusDecodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
);
BOOL WINAPI Asn1CmcAddExtensionsEncodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCMC_ADD_EXTENSIONS_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
);
BOOL WINAPI Asn1CmcAddExtensionsDecodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
);
BOOL WINAPI Asn1CmcAddAttributesEncodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCMC_ADD_ATTRIBUTES_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
);
BOOL WINAPI Asn1CmcAddAttributesDecodeEx(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
);
static const CRYPT_OID_FUNC_ENTRY CmcEncodeExFuncTable[] = {
CMC_DATA, Asn1CmcDataEncodeEx,
CMC_RESPONSE, Asn1CmcResponseEncodeEx,
CMC_STATUS, Asn1CmcStatusEncodeEx,
CMC_ADD_EXTENSIONS, Asn1CmcAddExtensionsEncodeEx,
CMC_ADD_ATTRIBUTES, Asn1CmcAddAttributesEncodeEx,
};
#define CMC_ENCODE_EX_FUNC_COUNT (sizeof(CmcEncodeExFuncTable) / \
sizeof(CmcEncodeExFuncTable[0]))
static const CRYPT_OID_FUNC_ENTRY CmcDecodeExFuncTable[] = {
CMC_DATA, Asn1CmcDataDecodeEx,
CMC_RESPONSE, Asn1CmcResponseDecodeEx,
CMC_STATUS, Asn1CmcStatusDecodeEx,
CMC_ADD_EXTENSIONS, Asn1CmcAddExtensionsDecodeEx,
CMC_ADD_ATTRIBUTES, Asn1CmcAddAttributesDecodeEx,
};
#define CMC_DECODE_EX_FUNC_COUNT (sizeof(CmcDecodeExFuncTable) / \
sizeof(CmcDecodeExFuncTable[0]))
//+-------------------------------------------------------------------------
// Dll initialization
//--------------------------------------------------------------------------
BOOL MSAsnInit(
HMODULE hInst)
{
BOOL fRet;
DWORD dwExceptionCode;
if (NULL == (hCrypt32Dll = LoadLibraryA("crypt32.dll")))
goto LoadCrypt32DllError;
if (NULL == (pfnCryptInstallAsn1Module =
(PFN_CRYPT_INSTALL_ASN1_MODULE) GetProcAddress(
hCrypt32Dll, "I_CryptInstallAsn1Module")))
goto I_CryptInstallAsn1ModuleProcAddressError;
if (NULL == (pfnCryptUninstallAsn1Module =
(PFN_CRYPT_UNINSTALL_ASN1_MODULE) GetProcAddress(
hCrypt32Dll, "I_CryptUninstallAsn1Module")))
goto I_CryptUninstallAsn1ModuleProcAddressError;
if (NULL == (pfnCryptGetAsn1Encoder =
(PFN_CRYPT_GET_ASN1_ENCODER) GetProcAddress(
hCrypt32Dll, "I_CryptGetAsn1Encoder")))
goto I_CryptGetAsn1EncoderProcAddressError;
if (NULL == (pfnCryptGetAsn1Decoder =
(PFN_CRYPT_GET_ASN1_DECODER) GetProcAddress(
hCrypt32Dll, "I_CryptGetAsn1Decoder")))
goto I_CryptGetAsn1DecoderProcAddressError;
__try {
XMSASN_Module_Startup();
} __except(EXCEPTION_EXECUTE_HANDLER) {
dwExceptionCode = GetExceptionCode();
goto MSAsn1DllException;
}
if (0 == (hAsn1Module = pfnCryptInstallAsn1Module(XMSASN_Module, 0, NULL)))
goto InstallAsn1ModuleError;
if (!CryptInstallOIDFunctionAddress(
hInst,
X509_ASN_ENCODING,
CRYPT_OID_ENCODE_OBJECT_FUNC,
X509_ENCODE_FUNC_COUNT,
X509EncodeFuncTable,
0)) // dwFlags
goto InstallOidFuncError;
if (!CryptInstallOIDFunctionAddress(
hInst,
X509_ASN_ENCODING,
CRYPT_OID_DECODE_OBJECT_FUNC,
X509_DECODE_FUNC_COUNT,
X509DecodeFuncTable,
0)) // dwFlags
goto InstallOidFuncError;
if (!CryptInstallOIDFunctionAddress(
hInst,
X509_ASN_ENCODING,
CRYPT_OID_ENCODE_OBJECT_EX_FUNC,
CMC_ENCODE_EX_FUNC_COUNT,
CmcEncodeExFuncTable,
0)) // dwFlags
goto InstallOidFuncError;
if (!CryptInstallOIDFunctionAddress(
hInst,
X509_ASN_ENCODING,
CRYPT_OID_DECODE_OBJECT_EX_FUNC,
CMC_DECODE_EX_FUNC_COUNT,
CmcDecodeExFuncTable,
0)) // dwFlags
goto InstallOidFuncError;
fRet = TRUE;
CommonReturn:
return fRet;
InstallOidFuncError:
fRet = FALSE;
goto CommonReturn;
ErrorReturn:
fRet = FALSE;
if (hCrypt32Dll) {
FreeLibrary(hCrypt32Dll);
hCrypt32Dll = NULL;
}
pfnCryptInstallAsn1Module = NULL;
pfnCryptUninstallAsn1Module = NULL;
pfnCryptGetAsn1Encoder = NULL;
pfnCryptGetAsn1Decoder = NULL;
hAsn1Module = NULL;
goto CommonReturn;
TRACE_ERROR(LoadCrypt32DllError)
TRACE_ERROR(I_CryptInstallAsn1ModuleProcAddressError)
TRACE_ERROR(I_CryptUninstallAsn1ModuleProcAddressError)
TRACE_ERROR(I_CryptGetAsn1EncoderProcAddressError)
TRACE_ERROR(I_CryptGetAsn1DecoderProcAddressError)
SET_ERROR_VAR(MSAsn1DllException, dwExceptionCode)
TRACE_ERROR(InstallAsn1ModuleError)
}
void MSAsnTerm()
{
if (hAsn1Module) {
pfnCryptUninstallAsn1Module(hAsn1Module);
__try {
XMSASN_Module_Cleanup();
} __except(EXCEPTION_EXECUTE_HANDLER) {
}
hAsn1Module = NULL;
}
if (hCrypt32Dll) {
FreeLibrary(hCrypt32Dll);
hCrypt32Dll = NULL;
}
}
//+-------------------------------------------------------------------------
// ASN1 X509 v3 ASN.1 Set / Get functions
//
// Called by the ASN1 X509 encode/decode functions.
//
// Assumption: all types are UNBOUNDED.
//
// 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.
//--------------------------------------------------------------------------
//+-------------------------------------------------------------------------
// Set/Free/Get CTL Usage object identifiers
//--------------------------------------------------------------------------
static BOOL Asn1X509SetCtlUsage(
IN PCTL_USAGE pUsage,
OUT EnhancedKeyUsage *pAsn1
)
{
DWORD cId;
LPSTR *ppszId;
UsageIdentifier *pAsn1Id;
pAsn1->count = 0;
pAsn1->value = NULL;
cId = pUsage->cUsageIdentifier;
if (0 == cId)
return TRUE;
pAsn1Id = (UsageIdentifier *) CertAlloc(cId * sizeof(UsageIdentifier));
if (pAsn1Id == NULL)
return FALSE;
pAsn1->count = cId;
pAsn1->value = pAsn1Id;
ppszId = pUsage->rgpszUsageIdentifier;
for ( ; cId > 0; cId--, ppszId++, pAsn1Id++) {
if (!Asn1X509SetObjId(*ppszId, pAsn1Id))
return FALSE;
}
return TRUE;
}
static void Asn1X509FreeCtlUsage(
IN EnhancedKeyUsage *pAsn1)
{
if (pAsn1->value) {
CertFree(pAsn1->value);
pAsn1->value = NULL;
}
}
static void Asn1X509GetCtlUsage(
IN EnhancedKeyUsage *pAsn1,
IN DWORD dwFlags,
OUT PCTL_USAGE pUsage,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra = *ppbExtra;
LONG lAlignExtra;
DWORD cId;
UsageIdentifier *pAsn1Id;
LPSTR *ppszId;
cId = pAsn1->count;
lAlignExtra = INFO_LEN_ALIGN(cId * sizeof(LPSTR));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
pUsage->cUsageIdentifier = cId;
ppszId = (LPSTR *) pbExtra;
pUsage->rgpszUsageIdentifier = ppszId;
pbExtra += lAlignExtra;
} else
ppszId = NULL;
pAsn1Id = pAsn1->value;
for ( ; cId > 0; cId--, pAsn1Id++, ppszId++)
Asn1X509GetObjId(pAsn1Id, dwFlags, ppszId, &pbExtra, &lRemainExtra);
*plRemainExtra = lRemainExtra;
*ppbExtra = pbExtra;
}
//+-------------------------------------------------------------------------
// CTL Usage (Enhanced Key Usage) Encode (ASN1 X509)
//--------------------------------------------------------------------------
static BOOL WINAPI Asn1X509CtlUsageEncode(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN PCTL_USAGE pInfo,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
EnhancedKeyUsage Asn1Info;
if (!Asn1X509SetCtlUsage(pInfo, &Asn1Info)) {
*pcbEncoded = 0;
fResult = FALSE;
} else
fResult = Asn1InfoEncode(
EnhancedKeyUsage_PDU,
&Asn1Info,
pbEncoded,
pcbEncoded
);
Asn1X509FreeCtlUsage(&Asn1Info);
return fResult;
}
//+-------------------------------------------------------------------------
// CTL Usage (Enhanced Key Usage) Decode (ASN1 X509)
//--------------------------------------------------------------------------
static BOOL WINAPI Asn1X509CtlUsageDecode(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
OUT PCTL_USAGE pInfo,
IN OUT DWORD *pcbInfo
)
{
BOOL fResult;
EnhancedKeyUsage *pAsn1Info = NULL;
BYTE *pbExtra;
LONG lRemainExtra;
if (pInfo == NULL)
*pcbInfo = 0;
if (!Asn1InfoDecodeAndAlloc(
EnhancedKeyUsage_PDU,
pbEncoded,
cbEncoded,
(void **) &pAsn1Info))
goto ErrorReturn;
// for lRemainExtra < 0, LENGTH_ONLY calculation
lRemainExtra = (LONG) *pcbInfo - sizeof(CTL_USAGE);
if (lRemainExtra < 0) {
pbExtra = NULL;
} else
pbExtra = (BYTE *) pInfo + sizeof(CTL_USAGE);
Asn1X509GetCtlUsage(pAsn1Info, dwFlags, pInfo, &pbExtra, &lRemainExtra);
if (lRemainExtra >= 0)
*pcbInfo = *pcbInfo - (DWORD) lRemainExtra;
else {
*pcbInfo = *pcbInfo + (DWORD) -lRemainExtra;
if (pInfo) goto LengthError;
}
fResult = TRUE;
goto CommonReturn;
LengthError:
SetLastError((DWORD) ERROR_MORE_DATA);
fResult = FALSE;
goto CommonReturn;
ErrorReturn:
*pcbInfo = 0;
fResult = FALSE;
CommonReturn:
Asn1InfoFree(EnhancedKeyUsage_PDU, pAsn1Info);
return fResult;
}
//+-------------------------------------------------------------------------
// Request Info Encode
//--------------------------------------------------------------------------
static BOOL WINAPI Asn1RequestInfoEncode(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN RequestFlags * pInfo,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
fResult = Asn1InfoEncode(
RequestFlags_PDU,
pInfo,
pbEncoded,
pcbEncoded
);
return fResult;
}
//+-------------------------------------------------------------------------
// Request Info Decode
//--------------------------------------------------------------------------
static BOOL WINAPI Asn1RequestInfoDecode(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD /*dwFlags*/,
OUT RequestFlags * pInfo,
IN OUT DWORD *pcbInfo
)
{
BOOL fResult;
RequestFlags * pAsn1 = NULL;
if (NULL == pInfo || NULL == pcbInfo)
goto ParamError;
if( *pcbInfo < sizeof(RequestFlags) )
goto LengthError;
else if (!Asn1InfoDecodeAndAlloc(
RequestFlags_PDU,
pbEncoded,
cbEncoded,
(void **) &pAsn1) || NULL == pAsn1)
goto ErrorReturn;
memcpy(pInfo, pAsn1, sizeof(RequestFlags));
fResult = TRUE;
goto CommonReturn;
ParamError:
SetLastError((DWORD)ERROR_INVALID_PARAMETER);
fResult = FALSE;
goto CommonReturn;
LengthError:
SetLastError((DWORD) ERROR_MORE_DATA);
fResult = FALSE;
goto CommonReturn;
ErrorReturn:
*pcbInfo = 0;
fResult = FALSE;
CommonReturn:
if (NULL != pAsn1)
{
Asn1InfoFree(RequestFlags_PDU, pAsn1);
}
return fResult;
}
static BOOL WINAPI Asn1CSPProviderEncode(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN PCRYPT_CSP_PROVIDER pCSPProvider,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
CSPProvider CspProvider;
CspProvider.keySpec = (int) pCSPProvider->dwKeySpec;
CspProvider.cspName.length = (DWORD)wcslen(pCSPProvider->pwszProviderName);
CspProvider.cspName.value = pCSPProvider->pwszProviderName;
PkiAsn1SetBitString(&pCSPProvider->Signature, &CspProvider.signature.length, &CspProvider.signature.value);
fResult = Asn1InfoEncode(
CSPProvider_PDU,
&CspProvider,
pbEncoded,
pcbEncoded
);
return fResult;
}
static BOOL WINAPI Asn1NameValueEncode(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN PCRYPT_ENROLLMENT_NAME_VALUE_PAIR pNameValue,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
EnrollmentNameValuePair NameValue;
NameValue.name.length = (DWORD)wcslen(pNameValue->pwszName);
NameValue.name.value = pNameValue->pwszName;
NameValue.value.length = (DWORD)wcslen(pNameValue->pwszValue);
NameValue.value.value = pNameValue->pwszValue;
fResult = Asn1InfoEncode(
EnrollmentNameValuePair_PDU,
&NameValue,
pbEncoded,
pcbEncoded
);
return fResult;
}
//+=========================================================================
// Certificate Management Messages over CMS (CMC) Encode/Decode Functions
//==========================================================================
//+-------------------------------------------------------------------------
// Encode an ASN1 formatted info structure
//
// Called by the Asn1X509*Encode() functions.
//--------------------------------------------------------------------------
static BOOL Asn1InfoEncodeEx(
IN int pdunum,
IN void *pvAsn1Info,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
return PkiAsn1EncodeInfoEx(
GetEncoder(),
pdunum,
pvAsn1Info,
dwFlags,
pEncodePara,
pvEncoded,
pcbEncoded);
}
//+-------------------------------------------------------------------------
// Decode into an ASN1 formatted info structure. Call the callback
// function to convert into the 'C' data structure. If
// CRYPT_DECODE_ALLOC_FLAG is set, call the callback twice. First,
// to get the length of the 'C' data structure. Then after allocating,
// call again to update the 'C' data structure.
//
// Called by the Asn1X509*Decode() functions.
//--------------------------------------------------------------------------
static BOOL Asn1InfoDecodeAndAllocEx(
IN int pdunum,
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
)
{
return PkiAsn1DecodeAndAllocInfoEx(
GetDecoder(),
pdunum,
pbEncoded,
cbEncoded,
dwFlags,
pDecodePara,
pfnDecodeExCallback,
pvStructInfo,
pcbStructInfo
);
}
//+-------------------------------------------------------------------------
// Set/Get CRYPT_DATA_BLOB (Octet String)
//--------------------------------------------------------------------------
inline void Asn1X509SetOctetString(
IN PCRYPT_DATA_BLOB pInfo,
OUT OCTETSTRING *pAsn1
)
{
pAsn1->value = pInfo->pbData;
pAsn1->length = pInfo->cbData;
}
inline void Asn1X509GetOctetString(
IN OCTETSTRING *pAsn1,
IN DWORD dwFlags,
OUT PCRYPT_DATA_BLOB pInfo,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
PkiAsn1GetOctetString(pAsn1->length, pAsn1->value, dwFlags,
pInfo, ppbExtra, plRemainExtra);
}
//+-------------------------------------------------------------------------
// Set/Get "Any" DER BLOB
//--------------------------------------------------------------------------
inline void Asn1X509SetAny(
IN PCRYPT_OBJID_BLOB pInfo,
OUT NOCOPYANY *pAsn1
)
{
PkiAsn1SetAny(pInfo, pAsn1);
}
inline void Asn1X509GetAny(
IN NOCOPYANY *pAsn1,
IN DWORD dwFlags,
OUT PCRYPT_OBJID_BLOB pInfo,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
PkiAsn1GetAny(pAsn1, dwFlags, pInfo, ppbExtra, plRemainExtra);
}
//+-------------------------------------------------------------------------
// Set/Free/Get SeqOfAny
//--------------------------------------------------------------------------
BOOL WINAPI Asn1X509SetSeqOfAny(
IN DWORD cValue,
IN PCRYPT_DER_BLOB pValue,
OUT ASN1uint32_t *pAsn1Count,
OUT NOCOPYANY **ppAsn1Value
)
{
*pAsn1Count = 0;
*ppAsn1Value = NULL;
if (cValue > 0) {
NOCOPYANY *pAsn1Value;
pAsn1Value = (NOCOPYANY *) PkiZeroAlloc(cValue * sizeof(NOCOPYANY));
if (pAsn1Value == NULL)
return FALSE;
*pAsn1Count = cValue;
*ppAsn1Value = pAsn1Value;
for ( ; cValue > 0; cValue--, pValue++, pAsn1Value++)
Asn1X509SetAny(pValue, pAsn1Value);
}
return TRUE;
}
void Asn1X509FreeSeqOfAny(
IN NOCOPYANY *pAsn1Value
)
{
if (pAsn1Value)
PkiFree(pAsn1Value);
}
void Asn1X509GetSeqOfAny(
IN unsigned int Asn1Count,
IN NOCOPYANY *pAsn1Value,
IN DWORD dwFlags,
OUT DWORD *pcValue,
OUT PCRYPT_DER_BLOB *ppValue,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lAlignExtra;
PCRYPT_ATTR_BLOB pValue;
lAlignExtra = INFO_LEN_ALIGN(Asn1Count * sizeof(CRYPT_DER_BLOB));
*plRemainExtra -= lAlignExtra;
if (*plRemainExtra >= 0) {
*pcValue = Asn1Count;
pValue = (PCRYPT_DER_BLOB) *ppbExtra;
*ppValue = pValue;
*ppbExtra += lAlignExtra;
} else
pValue = NULL;
for (; Asn1Count > 0; Asn1Count--, pAsn1Value++, pValue++)
Asn1X509GetAny(pAsn1Value, dwFlags, pValue, ppbExtra, plRemainExtra);
}
//+-------------------------------------------------------------------------
// Set/Free/Get Extensions
//--------------------------------------------------------------------------
BOOL Asn1X509SetExtensions(
IN DWORD cExtension,
IN PCERT_EXTENSION pExtension,
OUT Extensions *pAsn1
)
{
Extension *pAsn1Ext;
pAsn1->value = NULL;
pAsn1->count = 0;
if (cExtension == 0)
return TRUE;
pAsn1Ext = (Extension *) PkiZeroAlloc(cExtension * sizeof(Extension));
if (pAsn1Ext == NULL)
return FALSE;
pAsn1->value = pAsn1Ext;
pAsn1->count = cExtension;
for ( ; cExtension > 0; cExtension--, pExtension++, pAsn1Ext++) {
if (!Asn1X509SetObjId(pExtension->pszObjId, &pAsn1Ext->extnId))
return FALSE;
if (pExtension->fCritical) {
pAsn1Ext->critical = TRUE;
pAsn1Ext->bit_mask |= critical_present;
}
Asn1X509SetOctetString(&pExtension->Value, &pAsn1Ext->extnValue);
}
return TRUE;
}
void Asn1X509FreeExtensions(
IN Extensions *pAsn1)
{
if (pAsn1->value) {
PkiFree(pAsn1->value);
pAsn1->value = NULL;
}
pAsn1->count = 0;
}
void Asn1X509GetExtensions(
IN Extensions *pAsn1,
IN DWORD dwFlags,
OUT DWORD *pcExtension,
OUT PCERT_EXTENSION *ppExtension,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra = *ppbExtra;
LONG lAlignExtra;
DWORD cExt;
Extension *pAsn1Ext;
PCERT_EXTENSION pGetExt;
cExt = pAsn1->count;
lAlignExtra = INFO_LEN_ALIGN(cExt * sizeof(CERT_EXTENSION));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
*pcExtension = cExt;
pGetExt = (PCERT_EXTENSION) pbExtra;
*ppExtension = pGetExt;
pbExtra += lAlignExtra;
} else
pGetExt = NULL;
pAsn1Ext = pAsn1->value;
for ( ; cExt > 0; cExt--, pAsn1Ext++, pGetExt++) {
Asn1X509GetObjId(&pAsn1Ext->extnId, dwFlags, &pGetExt->pszObjId,
&pbExtra, &lRemainExtra);
if (lRemainExtra >= 0) {
pGetExt->fCritical = FALSE;
if (pAsn1Ext->bit_mask & critical_present)
pGetExt->fCritical = (BOOLEAN) pAsn1Ext->critical;
}
Asn1X509GetOctetString(&pAsn1Ext->extnValue, dwFlags, &pGetExt->Value,
&pbExtra, &lRemainExtra);
}
*plRemainExtra = lRemainExtra;
*ppbExtra = pbExtra;
}
//+-------------------------------------------------------------------------
// Set/Free/Get CRYPT_ATTRIBUTE
//--------------------------------------------------------------------------
BOOL WINAPI Asn1X509SetAttribute(
IN PCRYPT_ATTRIBUTE pInfo,
OUT Attribute *pAsn1
)
{
memset(pAsn1, 0, sizeof(*pAsn1));
if (!Asn1X509SetObjId(pInfo->pszObjId, &pAsn1->type))
return FALSE;
return Asn1X509SetSeqOfAny(
pInfo->cValue,
pInfo->rgValue,
&pAsn1->values.count,
&pAsn1->values.value);
}
void Asn1X509FreeAttribute(
IN OUT Attribute *pAsn1
)
{
Asn1X509FreeSeqOfAny(pAsn1->values.value);
}
void Asn1X509GetAttribute(
IN Attribute *pAsn1,
IN DWORD dwFlags,
OUT PCRYPT_ATTRIBUTE pInfo,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
Asn1X509GetObjId(&pAsn1->type, dwFlags,
&pInfo->pszObjId, ppbExtra, plRemainExtra);
Asn1X509GetSeqOfAny(pAsn1->values.count, pAsn1->values.value, dwFlags,
&pInfo->cValue, &pInfo->rgValue, ppbExtra, plRemainExtra);
}
//+-------------------------------------------------------------------------
// Set/Free/Get Attributes
//--------------------------------------------------------------------------
BOOL Asn1X509SetAttributes(
IN DWORD cAttribute,
IN PCRYPT_ATTRIBUTE pAttribute,
OUT Attributes *pAsn1
)
{
Attribute *pAsn1Attr;
pAsn1->value = NULL;
pAsn1->count = 0;
if (cAttribute == 0)
return TRUE;
pAsn1Attr = (Attribute *) PkiZeroAlloc(cAttribute * sizeof(Attribute));
if (pAsn1Attr == NULL)
return FALSE;
pAsn1->value = pAsn1Attr;
pAsn1->count = cAttribute;
for ( ; cAttribute > 0; cAttribute--, pAttribute++, pAsn1Attr++) {
if (!Asn1X509SetAttribute(pAttribute, pAsn1Attr))
return FALSE;
}
return TRUE;
}
void Asn1X509FreeAttributes(
IN Attributes *pAsn1
)
{
if (pAsn1->value) {
DWORD cAttr = pAsn1->count;
Attribute *pAsn1Attr = pAsn1->value;
for ( ; cAttr > 0; cAttr--, pAsn1Attr++)
Asn1X509FreeAttribute(pAsn1Attr);
PkiFree(pAsn1->value);
pAsn1->value = NULL;
}
pAsn1->count = 0;
}
void Asn1X509GetAttributes(
IN Attributes *pAsn1,
IN DWORD dwFlags,
OUT DWORD *pcAttribute,
OUT PCRYPT_ATTRIBUTE *ppAttribute,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra = *ppbExtra;
LONG lAlignExtra;
DWORD cAttr;
Attribute *pAsn1Attr;
PCRYPT_ATTRIBUTE pGetAttr;
cAttr = pAsn1->count;
lAlignExtra = INFO_LEN_ALIGN(cAttr * sizeof(CRYPT_ATTRIBUTE));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
*pcAttribute = cAttr;
pGetAttr = (PCRYPT_ATTRIBUTE) pbExtra;
*ppAttribute = pGetAttr;
pbExtra += lAlignExtra;
} else
pGetAttr = NULL;
pAsn1Attr = pAsn1->value;
for ( ; cAttr > 0; cAttr--, pAsn1Attr++, pGetAttr++) {
Asn1X509GetAttribute(pAsn1Attr, dwFlags, pGetAttr,
&pbExtra, &lRemainExtra);
}
*plRemainExtra = lRemainExtra;
*ppbExtra = pbExtra;
}
//+-------------------------------------------------------------------------
// Set/Free/Get CMC Tagged Attributes
//--------------------------------------------------------------------------
BOOL Asn1CmcSetTaggedAttributes(
IN DWORD cTaggedAttr,
IN PCMC_TAGGED_ATTRIBUTE pTaggedAttr,
OUT ControlSequence *pAsn1
)
{
TaggedAttribute *pAsn1Attr;
pAsn1->value = NULL;
pAsn1->count = 0;
if (cTaggedAttr == 0)
return TRUE;
pAsn1Attr = (TaggedAttribute *) PkiZeroAlloc(
cTaggedAttr * sizeof(TaggedAttribute));
if (pAsn1Attr == NULL)
return FALSE;
pAsn1->value = pAsn1Attr;
pAsn1->count = cTaggedAttr;
for ( ; cTaggedAttr > 0; cTaggedAttr--, pTaggedAttr++, pAsn1Attr++) {
pAsn1Attr->bodyPartID = pTaggedAttr->dwBodyPartID;
if (!Asn1X509SetObjId(pTaggedAttr->Attribute.pszObjId,
&pAsn1Attr->type))
return FALSE;
if (!Asn1X509SetSeqOfAny(
pTaggedAttr->Attribute.cValue,
pTaggedAttr->Attribute.rgValue,
&pAsn1Attr->values.count,
&pAsn1Attr->values.value))
return FALSE;
}
return TRUE;
}
void Asn1CmcFreeTaggedAttributes(
IN OUT ControlSequence *pAsn1
)
{
if (pAsn1->value) {
TaggedAttribute *pAsn1Attr = pAsn1->value;
DWORD cTaggedAttr = pAsn1->count;
for ( ; cTaggedAttr > 0; cTaggedAttr--, pAsn1Attr++) {
Asn1X509FreeSeqOfAny(pAsn1Attr->values.value);
}
PkiFree(pAsn1->value);
pAsn1->value = NULL;
}
pAsn1->count = 0;
}
void Asn1CmcGetTaggedAttributes(
IN ControlSequence *pAsn1,
IN DWORD dwFlags,
OUT DWORD *pcTaggedAttr,
OUT PCMC_TAGGED_ATTRIBUTE *ppTaggedAttr,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra = *ppbExtra;
LONG lAlignExtra;
DWORD cTaggedAttr;
TaggedAttribute *pAsn1Attr;
PCMC_TAGGED_ATTRIBUTE pTaggedAttr;
cTaggedAttr = pAsn1->count;
lAlignExtra = INFO_LEN_ALIGN(cTaggedAttr * sizeof(CMC_TAGGED_ATTRIBUTE));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
*pcTaggedAttr = cTaggedAttr;
pTaggedAttr = (PCMC_TAGGED_ATTRIBUTE) pbExtra;
*ppTaggedAttr = pTaggedAttr;
pbExtra += lAlignExtra;
} else
pTaggedAttr = NULL;
pAsn1Attr = pAsn1->value;
for ( ; cTaggedAttr > 0; cTaggedAttr--, pAsn1Attr++, pTaggedAttr++) {
if (lRemainExtra >= 0) {
pTaggedAttr->dwBodyPartID = pAsn1Attr->bodyPartID;
}
Asn1X509GetObjId(&pAsn1Attr->type, dwFlags,
&pTaggedAttr->Attribute.pszObjId, &pbExtra, &lRemainExtra);
Asn1X509GetSeqOfAny(
pAsn1Attr->values.count, pAsn1Attr->values.value, dwFlags,
&pTaggedAttr->Attribute.cValue, &pTaggedAttr->Attribute.rgValue,
&pbExtra, &lRemainExtra);
}
*plRemainExtra = lRemainExtra;
*ppbExtra = pbExtra;
}
//+-------------------------------------------------------------------------
// Set/Free/Get CMC Tagged Requests
//--------------------------------------------------------------------------
BOOL Asn1CmcSetTaggedRequests(
IN DWORD cTaggedReq,
IN PCMC_TAGGED_REQUEST pTaggedReq,
OUT ReqSequence *pAsn1
)
{
TaggedRequest *pAsn1Req;
pAsn1->value = NULL;
pAsn1->count = 0;
if (cTaggedReq == 0)
return TRUE;
pAsn1Req = (TaggedRequest *) PkiZeroAlloc(
cTaggedReq * sizeof(TaggedRequest));
if (pAsn1Req == NULL)
return FALSE;
pAsn1->value = pAsn1Req;
pAsn1->count = cTaggedReq;
for ( ; cTaggedReq > 0; cTaggedReq--, pTaggedReq++, pAsn1Req++) {
PCMC_TAGGED_CERT_REQUEST pTaggedCertReq;
TaggedCertificationRequest *ptcr;
if (CMC_TAGGED_CERT_REQUEST_CHOICE !=
pTaggedReq->dwTaggedRequestChoice) {
SetLastError((DWORD) E_INVALIDARG);
return FALSE;
}
pAsn1Req->choice = tcr_chosen;
ptcr = &pAsn1Req->u.tcr;
pTaggedCertReq = pTaggedReq->pTaggedCertRequest;
ptcr->bodyPartID = pTaggedCertReq->dwBodyPartID;
Asn1X509SetAny(&pTaggedCertReq->SignedCertRequest,
&ptcr->certificationRequest);
}
return TRUE;
}
void Asn1CmcFreeTaggedRequests(
IN OUT ReqSequence *pAsn1
)
{
if (pAsn1->value) {
PkiFree(pAsn1->value);
pAsn1->value = NULL;
}
pAsn1->count = 0;
}
BOOL Asn1CmcGetTaggedRequests(
IN ReqSequence *pAsn1,
IN DWORD dwFlags,
OUT DWORD *pcTaggedReq,
OUT PCMC_TAGGED_REQUEST *ppTaggedReq,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
BOOL fResult;
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra = *ppbExtra;
LONG lAlignExtra;
DWORD cTaggedReq;
TaggedRequest *pAsn1Req;
PCMC_TAGGED_REQUEST pTaggedReq;
cTaggedReq = pAsn1->count;
lAlignExtra = INFO_LEN_ALIGN(cTaggedReq * sizeof(CMC_TAGGED_REQUEST));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
*pcTaggedReq = cTaggedReq;
pTaggedReq = (PCMC_TAGGED_REQUEST) pbExtra;
*ppTaggedReq = pTaggedReq;
pbExtra += lAlignExtra;
} else
pTaggedReq = NULL;
pAsn1Req = pAsn1->value;
for ( ; cTaggedReq > 0; cTaggedReq--, pAsn1Req++, pTaggedReq++) {
PCMC_TAGGED_CERT_REQUEST pTaggedCertReq;
TaggedCertificationRequest *ptcr;
if (tcr_chosen != pAsn1Req->choice) {
SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
goto ErrorReturn;
}
ptcr = &pAsn1Req->u.tcr;
lAlignExtra = INFO_LEN_ALIGN(sizeof(CMC_TAGGED_CERT_REQUEST));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
pTaggedReq->dwTaggedRequestChoice =
CMC_TAGGED_CERT_REQUEST_CHOICE;
pTaggedCertReq = (PCMC_TAGGED_CERT_REQUEST) pbExtra;
pbExtra += lAlignExtra;
pTaggedReq->pTaggedCertRequest = pTaggedCertReq;
pTaggedCertReq->dwBodyPartID = ptcr->bodyPartID;
} else
pTaggedCertReq = NULL;
Asn1X509GetAny(&ptcr->certificationRequest, dwFlags,
&pTaggedCertReq->SignedCertRequest, &pbExtra, &lRemainExtra);
}
*plRemainExtra = lRemainExtra;
*ppbExtra = pbExtra;
fResult = TRUE;
CommonReturn:
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
}
//+-------------------------------------------------------------------------
// Set/Free/Get CMC Tagged ContentInfo
//--------------------------------------------------------------------------
BOOL Asn1CmcSetTaggedContentInfos(
IN DWORD cTaggedCI,
IN PCMC_TAGGED_CONTENT_INFO pTaggedCI,
OUT CmsSequence *pAsn1
)
{
TaggedContentInfo *pAsn1CI;
pAsn1->value = NULL;
pAsn1->count = 0;
if (cTaggedCI == 0)
return TRUE;
pAsn1CI = (TaggedContentInfo *) PkiZeroAlloc(
cTaggedCI * sizeof(TaggedContentInfo));
if (pAsn1CI == NULL)
return FALSE;
pAsn1->value = pAsn1CI;
pAsn1->count = cTaggedCI;
for ( ; cTaggedCI > 0; cTaggedCI--, pTaggedCI++, pAsn1CI++) {
pAsn1CI->bodyPartID = pTaggedCI->dwBodyPartID;
Asn1X509SetAny(&pTaggedCI->EncodedContentInfo, &pAsn1CI->contentInfo);
}
return TRUE;
}
void Asn1CmcFreeTaggedContentInfos(
IN OUT CmsSequence *pAsn1
)
{
if (pAsn1->value) {
PkiFree(pAsn1->value);
pAsn1->value = NULL;
}
pAsn1->count = 0;
}
void Asn1CmcGetTaggedContentInfos(
IN CmsSequence *pAsn1,
IN DWORD dwFlags,
OUT DWORD *pcTaggedCI,
OUT PCMC_TAGGED_CONTENT_INFO *ppTaggedCI,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra = *ppbExtra;
LONG lAlignExtra;
DWORD cTaggedCI;
TaggedContentInfo *pAsn1CI;
PCMC_TAGGED_CONTENT_INFO pTaggedCI;
cTaggedCI = pAsn1->count;
lAlignExtra = INFO_LEN_ALIGN(cTaggedCI * sizeof(CMC_TAGGED_CONTENT_INFO));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
*pcTaggedCI = cTaggedCI;
pTaggedCI = (PCMC_TAGGED_CONTENT_INFO) pbExtra;
*ppTaggedCI = pTaggedCI;
pbExtra += lAlignExtra;
} else
pTaggedCI = NULL;
pAsn1CI = pAsn1->value;
for ( ; cTaggedCI > 0; cTaggedCI--, pAsn1CI++, pTaggedCI++) {
if (lRemainExtra >= 0) {
pTaggedCI->dwBodyPartID = pAsn1CI->bodyPartID;
}
Asn1X509GetAny(&pAsn1CI->contentInfo, dwFlags,
&pTaggedCI->EncodedContentInfo, &pbExtra, &lRemainExtra);
}
*plRemainExtra = lRemainExtra;
*ppbExtra = pbExtra;
}
//+-------------------------------------------------------------------------
// Set/Free/Get CMC Tagged OtherMsg
//--------------------------------------------------------------------------
BOOL Asn1CmcSetTaggedOtherMsgs(
IN DWORD cTaggedOM,
IN PCMC_TAGGED_OTHER_MSG pTaggedOM,
OUT OtherMsgSequence *pAsn1
)
{
TaggedOtherMsg *pAsn1OM;
pAsn1->value = NULL;
pAsn1->count = 0;
if (cTaggedOM == 0)
return TRUE;
pAsn1OM = (TaggedOtherMsg *) PkiZeroAlloc(
cTaggedOM * sizeof(TaggedOtherMsg));
if (pAsn1OM == NULL)
return FALSE;
pAsn1->value = pAsn1OM;
pAsn1->count = cTaggedOM;
for ( ; cTaggedOM > 0; cTaggedOM--, pTaggedOM++, pAsn1OM++) {
pAsn1OM->bodyPartID = pTaggedOM->dwBodyPartID;
if (!Asn1X509SetObjId(pTaggedOM->pszObjId,
&pAsn1OM->otherMsgType))
return FALSE;
Asn1X509SetAny(&pTaggedOM->Value, &pAsn1OM->otherMsgValue);
}
return TRUE;
}
void Asn1CmcFreeTaggedOtherMsgs(
IN OUT OtherMsgSequence *pAsn1
)
{
if (pAsn1->value) {
PkiFree(pAsn1->value);
pAsn1->value = NULL;
}
pAsn1->count = 0;
}
void Asn1CmcGetTaggedOtherMsgs(
IN OtherMsgSequence *pAsn1,
IN DWORD dwFlags,
OUT DWORD *pcTaggedOM,
OUT PCMC_TAGGED_OTHER_MSG *ppTaggedOM,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra = *ppbExtra;
LONG lAlignExtra;
DWORD cTaggedOM;
TaggedOtherMsg *pAsn1OM;
PCMC_TAGGED_OTHER_MSG pTaggedOM;
cTaggedOM = pAsn1->count;
lAlignExtra = INFO_LEN_ALIGN(cTaggedOM * sizeof(CMC_TAGGED_OTHER_MSG));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
*pcTaggedOM = cTaggedOM;
pTaggedOM = (PCMC_TAGGED_OTHER_MSG) pbExtra;
*ppTaggedOM = pTaggedOM;
pbExtra += lAlignExtra;
} else
pTaggedOM = NULL;
pAsn1OM = pAsn1->value;
for ( ; cTaggedOM > 0; cTaggedOM--, pAsn1OM++, pTaggedOM++) {
if (lRemainExtra >= 0) {
pTaggedOM->dwBodyPartID = pAsn1OM->bodyPartID;
}
Asn1X509GetObjId(&pAsn1OM->otherMsgType, dwFlags,
&pTaggedOM->pszObjId, &pbExtra, &lRemainExtra);
Asn1X509GetAny(&pAsn1OM->otherMsgValue, dwFlags,
&pTaggedOM->Value, &pbExtra, &lRemainExtra);
}
*plRemainExtra = lRemainExtra;
*ppbExtra = pbExtra;
}
//+-------------------------------------------------------------------------
// CMC Data Encode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcDataEncodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN PCMC_DATA_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
CmcData Asn1Info;
memset(&Asn1Info, 0, sizeof(Asn1Info));
if (!Asn1CmcSetTaggedAttributes(pInfo->cTaggedAttribute,
pInfo->rgTaggedAttribute, &Asn1Info.controlSequence))
goto ErrorReturn;
if (!Asn1CmcSetTaggedRequests(pInfo->cTaggedRequest,
pInfo->rgTaggedRequest, &Asn1Info.reqSequence))
goto ErrorReturn;
if (!Asn1CmcSetTaggedContentInfos(pInfo->cTaggedContentInfo,
pInfo->rgTaggedContentInfo, &Asn1Info.cmsSequence))
goto ErrorReturn;
if (!Asn1CmcSetTaggedOtherMsgs(pInfo->cTaggedOtherMsg,
pInfo->rgTaggedOtherMsg, &Asn1Info.otherMsgSequence))
goto ErrorReturn;
fResult = Asn1InfoEncodeEx(
CmcData_PDU,
&Asn1Info,
dwFlags,
pEncodePara,
pvEncoded,
pcbEncoded
);
CommonReturn:
Asn1CmcFreeTaggedAttributes(&Asn1Info.controlSequence);
Asn1CmcFreeTaggedRequests(&Asn1Info.reqSequence);
Asn1CmcFreeTaggedContentInfos(&Asn1Info.cmsSequence);
Asn1CmcFreeTaggedOtherMsgs(&Asn1Info.otherMsgSequence);
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
*((void **) pvEncoded) = NULL;
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
//+-------------------------------------------------------------------------
// CMC Data Decode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcDataDecodeExCallback(
IN void *pvAsn1Info,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
OUT OPTIONAL void *pvStructInfo,
IN OUT LONG *plRemainExtra
)
{
BOOL fResult;
CmcData *pAsn1 = (CmcData *) pvAsn1Info;
PCMC_DATA_INFO pInfo = (PCMC_DATA_INFO) pvStructInfo;
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra;
lRemainExtra -= sizeof(CMC_DATA_INFO);
if (lRemainExtra < 0) {
pbExtra = NULL;
} else {
memset(pInfo, 0, sizeof(CMC_DATA_INFO));
pbExtra = (BYTE *) pInfo + sizeof(CMC_DATA_INFO);
}
Asn1CmcGetTaggedAttributes(&pAsn1->controlSequence,
dwFlags,
&pInfo->cTaggedAttribute,
&pInfo->rgTaggedAttribute,
&pbExtra,
&lRemainExtra
);
if (!Asn1CmcGetTaggedRequests(&pAsn1->reqSequence,
dwFlags,
&pInfo->cTaggedRequest,
&pInfo->rgTaggedRequest,
&pbExtra,
&lRemainExtra
))
goto ErrorReturn;
Asn1CmcGetTaggedContentInfos(&pAsn1->cmsSequence,
dwFlags,
&pInfo->cTaggedContentInfo,
&pInfo->rgTaggedContentInfo,
&pbExtra,
&lRemainExtra
);
Asn1CmcGetTaggedOtherMsgs(&pAsn1->otherMsgSequence,
dwFlags,
&pInfo->cTaggedOtherMsg,
&pInfo->rgTaggedOtherMsg,
&pbExtra,
&lRemainExtra
);
fResult = TRUE;
CommonReturn:
*plRemainExtra = lRemainExtra;
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
}
BOOL WINAPI Asn1CmcDataDecodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
)
{
return Asn1InfoDecodeAndAllocEx(
CmcData_PDU,
pbEncoded,
cbEncoded,
dwFlags,
pDecodePara,
Asn1CmcDataDecodeExCallback,
pvStructInfo,
pcbStructInfo
);
}
//+-------------------------------------------------------------------------
// CMC Response Encode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcResponseEncodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN PCMC_RESPONSE_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
CmcResponseBody Asn1Info;
memset(&Asn1Info, 0, sizeof(Asn1Info));
if (!Asn1CmcSetTaggedAttributes(pInfo->cTaggedAttribute,
pInfo->rgTaggedAttribute, &Asn1Info.controlSequence))
goto ErrorReturn;
if (!Asn1CmcSetTaggedContentInfos(pInfo->cTaggedContentInfo,
pInfo->rgTaggedContentInfo, &Asn1Info.cmsSequence))
goto ErrorReturn;
if (!Asn1CmcSetTaggedOtherMsgs(pInfo->cTaggedOtherMsg,
pInfo->rgTaggedOtherMsg, &Asn1Info.otherMsgSequence))
goto ErrorReturn;
fResult = Asn1InfoEncodeEx(
CmcResponseBody_PDU,
&Asn1Info,
dwFlags,
pEncodePara,
pvEncoded,
pcbEncoded
);
CommonReturn:
Asn1CmcFreeTaggedAttributes(&Asn1Info.controlSequence);
Asn1CmcFreeTaggedContentInfos(&Asn1Info.cmsSequence);
Asn1CmcFreeTaggedOtherMsgs(&Asn1Info.otherMsgSequence);
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
*((void **) pvEncoded) = NULL;
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
//+-------------------------------------------------------------------------
// CMC Response Decode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcResponseDecodeExCallback(
IN void *pvAsn1Info,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
OUT OPTIONAL void *pvStructInfo,
IN OUT LONG *plRemainExtra
)
{
BOOL fResult;
CmcResponseBody *pAsn1 = (CmcResponseBody *) pvAsn1Info;
PCMC_RESPONSE_INFO pInfo = (PCMC_RESPONSE_INFO) pvStructInfo;
LONG lRemainExtra = *plRemainExtra;
BYTE *pbExtra;
lRemainExtra -= sizeof(CMC_RESPONSE_INFO);
if (lRemainExtra < 0) {
pbExtra = NULL;
} else {
memset(pInfo, 0, sizeof(CMC_RESPONSE_INFO));
pbExtra = (BYTE *) pInfo + sizeof(CMC_RESPONSE_INFO);
}
Asn1CmcGetTaggedAttributes(&pAsn1->controlSequence,
dwFlags,
&pInfo->cTaggedAttribute,
&pInfo->rgTaggedAttribute,
&pbExtra,
&lRemainExtra
);
Asn1CmcGetTaggedContentInfos(&pAsn1->cmsSequence,
dwFlags,
&pInfo->cTaggedContentInfo,
&pInfo->rgTaggedContentInfo,
&pbExtra,
&lRemainExtra
);
Asn1CmcGetTaggedOtherMsgs(&pAsn1->otherMsgSequence,
dwFlags,
&pInfo->cTaggedOtherMsg,
&pInfo->rgTaggedOtherMsg,
&pbExtra,
&lRemainExtra
);
fResult = TRUE;
*plRemainExtra = lRemainExtra;
return fResult;
}
BOOL WINAPI Asn1CmcResponseDecodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
)
{
return Asn1InfoDecodeAndAllocEx(
CmcResponseBody_PDU,
pbEncoded,
cbEncoded,
dwFlags,
pDecodePara,
Asn1CmcResponseDecodeExCallback,
pvStructInfo,
pcbStructInfo
);
}
//+-------------------------------------------------------------------------
// CMC Status Encode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcStatusEncodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN PCMC_STATUS_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
CmcStatusInfo Asn1Info;
memset(&Asn1Info, 0, sizeof(Asn1Info));
Asn1Info.cmcStatus = pInfo->dwStatus;
if (pInfo->cBodyList) {
Asn1Info.bodyList.count = pInfo->cBodyList;
Asn1Info.bodyList.value = pInfo->rgdwBodyList;
}
if (pInfo->pwszStatusString && L'\0' != *pInfo->pwszStatusString) {
Asn1Info.bit_mask |= statusString_present;
Asn1Info.statusString.length = (DWORD)wcslen(pInfo->pwszStatusString);
Asn1Info.statusString.value = pInfo->pwszStatusString;
}
if (CMC_OTHER_INFO_NO_CHOICE != pInfo->dwOtherInfoChoice) {
Asn1Info.bit_mask |= otherInfo_present;
switch (pInfo->dwOtherInfoChoice) {
case CMC_OTHER_INFO_FAIL_CHOICE:
Asn1Info.otherInfo.choice = failInfo_chosen;
Asn1Info.otherInfo.u.failInfo = pInfo->dwFailInfo;
break;
case CMC_OTHER_INFO_PEND_CHOICE:
Asn1Info.otherInfo.choice = pendInfo_chosen;
Asn1X509SetOctetString(&pInfo->pPendInfo->PendToken,
&Asn1Info.otherInfo.u.pendInfo.pendToken);
if (!PkiAsn1ToGeneralizedTime(
&pInfo->pPendInfo->PendTime,
&Asn1Info.otherInfo.u.pendInfo.pendTime))
goto GeneralizedTimeError;
break;
default:
goto InvalidOtherInfoChoiceError;
}
}
fResult = Asn1InfoEncodeEx(
CmcStatusInfo_PDU,
&Asn1Info,
dwFlags,
pEncodePara,
pvEncoded,
pcbEncoded
);
CommonReturn:
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
*((void **) pvEncoded) = NULL;
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
SET_ERROR(InvalidOtherInfoChoiceError, E_INVALIDARG)
SET_ERROR(GeneralizedTimeError, CRYPT_E_BAD_ENCODE)
}
//+-------------------------------------------------------------------------
// CMC Status Decode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcStatusDecodeExCallback(
IN void *pvAsn1Info,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
OUT OPTIONAL void *pvStructInfo,
IN OUT LONG *plRemainExtra
)
{
BOOL fResult;
CmcStatusInfo *pAsn1 = (CmcStatusInfo *) pvAsn1Info;
PCMC_STATUS_INFO pInfo = (PCMC_STATUS_INFO) pvStructInfo;
LONG lRemainExtra = *plRemainExtra;
LONG lAlignExtra;
BYTE *pbExtra;
lRemainExtra -= sizeof(CMC_STATUS_INFO);
if (lRemainExtra < 0) {
pbExtra = NULL;
} else {
memset(pInfo, 0, sizeof(CMC_STATUS_INFO));
pbExtra = (BYTE *) pInfo + sizeof(CMC_STATUS_INFO);
pInfo->dwStatus = pAsn1->cmcStatus;
}
if (pAsn1->bodyList.count > 0) {
ASN1uint32_t count = pAsn1->bodyList.count;
lAlignExtra = INFO_LEN_ALIGN(count * sizeof(DWORD));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
BodyPartID *value;
DWORD *pdwBodyList;
value = pAsn1->bodyList.value;
pdwBodyList = (DWORD *) pbExtra;
pbExtra += lAlignExtra;
pInfo->cBodyList = count;
pInfo->rgdwBodyList = pdwBodyList;
for ( ; count > 0; count--, value++, pdwBodyList++)
*pdwBodyList = *value;
}
}
if (pAsn1->bit_mask & statusString_present) {
ASN1uint32_t length = pAsn1->statusString.length;
lAlignExtra = INFO_LEN_ALIGN((length + 1) * sizeof(WCHAR));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
memcpy(pbExtra, pAsn1->statusString.value, length * sizeof(WCHAR));
memset(pbExtra + (length * sizeof(WCHAR)), 0, sizeof(WCHAR));
pInfo->pwszStatusString = (LPWSTR) pbExtra;
pbExtra += lAlignExtra;
}
}
if (pAsn1->bit_mask & otherInfo_present) {
switch (pAsn1->otherInfo.choice) {
case failInfo_chosen:
if (lRemainExtra >= 0) {
pInfo->dwOtherInfoChoice = CMC_OTHER_INFO_FAIL_CHOICE;
pInfo->dwFailInfo = pAsn1->otherInfo.u.failInfo;
}
break;
case pendInfo_chosen:
{
PCMC_PEND_INFO pPendInfo;
lAlignExtra = INFO_LEN_ALIGN(sizeof(CMC_PEND_INFO));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
pInfo->dwOtherInfoChoice = CMC_OTHER_INFO_PEND_CHOICE;
pPendInfo = (PCMC_PEND_INFO) pbExtra;
pInfo->pPendInfo = pPendInfo;
pbExtra += lAlignExtra;
if (!PkiAsn1FromGeneralizedTime(
&pAsn1->otherInfo.u.pendInfo.pendTime,
&pPendInfo->PendTime))
goto GeneralizedTimeDecodeError;
} else
pPendInfo = NULL;
Asn1X509GetOctetString(
&pAsn1->otherInfo.u.pendInfo.pendToken, dwFlags,
&pPendInfo->PendToken, &pbExtra, &lRemainExtra);
}
break;
default:
goto InvalidOtherInfoChoiceError;
}
}
fResult = TRUE;
CommonReturn:
*plRemainExtra = lRemainExtra;
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
SET_ERROR(InvalidOtherInfoChoiceError, CRYPT_E_BAD_ENCODE)
SET_ERROR(GeneralizedTimeDecodeError, CRYPT_E_BAD_ENCODE)
}
BOOL WINAPI Asn1CmcStatusDecodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
)
{
return Asn1InfoDecodeAndAllocEx(
CmcStatusInfo_PDU,
pbEncoded,
cbEncoded,
dwFlags,
pDecodePara,
Asn1CmcStatusDecodeExCallback,
pvStructInfo,
pcbStructInfo
);
}
//+-------------------------------------------------------------------------
// CMC Add Extensions Encode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcAddExtensionsEncodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN PCMC_ADD_EXTENSIONS_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
CmcAddExtensions Asn1Info;
memset(&Asn1Info, 0, sizeof(Asn1Info));
Asn1Info.pkiDataReference = pInfo->dwCmcDataReference;
if (pInfo->cCertReference) {
Asn1Info.certReferences.count = pInfo->cCertReference;
Asn1Info.certReferences.value = pInfo->rgdwCertReference;
}
if (!Asn1X509SetExtensions(pInfo->cExtension, pInfo->rgExtension,
&Asn1Info.extensions))
goto ErrorReturn;
fResult = Asn1InfoEncodeEx(
CmcAddExtensions_PDU,
&Asn1Info,
dwFlags,
pEncodePara,
pvEncoded,
pcbEncoded
);
CommonReturn:
Asn1X509FreeExtensions(&Asn1Info.extensions);
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
*((void **) pvEncoded) = NULL;
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
//+-------------------------------------------------------------------------
// CMC Add Extensions Decode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcAddExtensionsDecodeExCallback(
IN void *pvAsn1Info,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
OUT OPTIONAL void *pvStructInfo,
IN OUT LONG *plRemainExtra
)
{
BOOL fResult;
CmcAddExtensions *pAsn1 = (CmcAddExtensions *) pvAsn1Info;
PCMC_ADD_EXTENSIONS_INFO pInfo = (PCMC_ADD_EXTENSIONS_INFO) pvStructInfo;
LONG lRemainExtra = *plRemainExtra;
LONG lAlignExtra;
BYTE *pbExtra;
lRemainExtra -= sizeof(CMC_ADD_EXTENSIONS_INFO);
if (lRemainExtra < 0) {
pbExtra = NULL;
} else {
memset(pInfo, 0, sizeof(CMC_ADD_EXTENSIONS_INFO));
pbExtra = (BYTE *) pInfo + sizeof(CMC_ADD_EXTENSIONS_INFO);
pInfo->dwCmcDataReference = pAsn1->pkiDataReference;
}
if (pAsn1->certReferences.count > 0) {
ASN1uint32_t count = pAsn1->certReferences.count;
lAlignExtra = INFO_LEN_ALIGN(count * sizeof(DWORD));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
BodyPartID *value;
DWORD *pdwCertReference;
value = pAsn1->certReferences.value;
pdwCertReference = (DWORD *) pbExtra;
pbExtra += lAlignExtra;
pInfo->cCertReference = count;
pInfo->rgdwCertReference = pdwCertReference;
for ( ; count > 0; count--, value++, pdwCertReference++)
*pdwCertReference = *value;
}
}
Asn1X509GetExtensions(&pAsn1->extensions, dwFlags,
&pInfo->cExtension, &pInfo->rgExtension, &pbExtra, &lRemainExtra);
fResult = TRUE;
*plRemainExtra = lRemainExtra;
return fResult;
}
BOOL WINAPI Asn1CmcAddExtensionsDecodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
)
{
return Asn1InfoDecodeAndAllocEx(
CmcAddExtensions_PDU,
pbEncoded,
cbEncoded,
dwFlags,
pDecodePara,
Asn1CmcAddExtensionsDecodeExCallback,
pvStructInfo,
pcbStructInfo
);
}
//+-------------------------------------------------------------------------
// CMC Add Attributes Encode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcAddAttributesEncodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN PCMC_ADD_ATTRIBUTES_INFO pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
CmcAddAttributes Asn1Info;
memset(&Asn1Info, 0, sizeof(Asn1Info));
Asn1Info.pkiDataReference = pInfo->dwCmcDataReference;
if (pInfo->cCertReference) {
Asn1Info.certReferences.count = pInfo->cCertReference;
Asn1Info.certReferences.value = pInfo->rgdwCertReference;
}
if (!Asn1X509SetAttributes(pInfo->cAttribute, pInfo->rgAttribute,
&Asn1Info.attributes))
goto ErrorReturn;
fResult = Asn1InfoEncodeEx(
CmcAddAttributes_PDU,
&Asn1Info,
dwFlags,
pEncodePara,
pvEncoded,
pcbEncoded
);
CommonReturn:
Asn1X509FreeAttributes(&Asn1Info.attributes);
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
*((void **) pvEncoded) = NULL;
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
//+-------------------------------------------------------------------------
// CMC Add Attributes Decode (ASN1)
//--------------------------------------------------------------------------
BOOL WINAPI Asn1CmcAddAttributesDecodeExCallback(
IN void *pvAsn1Info,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
OUT OPTIONAL void *pvStructInfo,
IN OUT LONG *plRemainExtra
)
{
BOOL fResult;
CmcAddAttributes *pAsn1 = (CmcAddAttributes *) pvAsn1Info;
PCMC_ADD_ATTRIBUTES_INFO pInfo = (PCMC_ADD_ATTRIBUTES_INFO) pvStructInfo;
LONG lRemainExtra = *plRemainExtra;
LONG lAlignExtra;
BYTE *pbExtra;
lRemainExtra -= sizeof(CMC_ADD_ATTRIBUTES_INFO);
if (lRemainExtra < 0) {
pbExtra = NULL;
} else {
memset(pInfo, 0, sizeof(CMC_ADD_ATTRIBUTES_INFO));
pbExtra = (BYTE *) pInfo + sizeof(CMC_ADD_ATTRIBUTES_INFO);
pInfo->dwCmcDataReference = pAsn1->pkiDataReference;
}
if (pAsn1->certReferences.count > 0) {
ASN1uint32_t count = pAsn1->certReferences.count;
lAlignExtra = INFO_LEN_ALIGN(count * sizeof(DWORD));
lRemainExtra -= lAlignExtra;
if (lRemainExtra >= 0) {
BodyPartID *value;
DWORD *pdwCertReference;
value = pAsn1->certReferences.value;
pdwCertReference = (DWORD *) pbExtra;
pbExtra += lAlignExtra;
pInfo->cCertReference = count;
pInfo->rgdwCertReference = pdwCertReference;
for ( ; count > 0; count--, value++, pdwCertReference++)
*pdwCertReference = *value;
}
}
Asn1X509GetAttributes(&pAsn1->attributes, dwFlags,
&pInfo->cAttribute, &pInfo->rgAttribute, &pbExtra, &lRemainExtra);
fResult = TRUE;
*plRemainExtra = lRemainExtra;
return fResult;
}
BOOL WINAPI Asn1CmcAddAttributesDecodeEx(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
OUT OPTIONAL void *pvStructInfo,
IN OUT DWORD *pcbStructInfo
)
{
return Asn1InfoDecodeAndAllocEx(
CmcAddAttributes_PDU,
pbEncoded,
cbEncoded,
dwFlags,
pDecodePara,
Asn1CmcAddAttributesDecodeExCallback,
pvStructInfo,
pcbStructInfo
);
}