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.
 
 
 
 
 
 

646 lines
18 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: attrbute.cpp
//
// Contents:
// Encode/Decode APIs
//
// ASN.1 implementation uses the OSS compiler.
//
// Functions: CryptEncodeObject
// CryptDecodeObject
//
// History: 29-Feb-96 philh created
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include <windows.h>
#include <wincrypt.h>
#include <malloc.h>
#include "xenroll.h"
#include "cenroll.h"
#include "ossconv.h"
#include "ossutil.h"
#include "asn1util.h"
#include "crypttls.h"
extern "C"
{
#include "xasn.h"
}
// All the *pvInfo extra stuff needs to be aligned
#define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
HCRYPTOSSGLOBAL hX509OssGlobal;
//+-------------------------------------------------------------------------
// Function: GetPog
//
// Synopsis: Initialize thread local storage for the asn libs
//
// Returns: pointer to an initialized OssGlobal data structure
//--------------------------------------------------------------------------
static inline POssGlobal GetPog(void)
{
return I_CryptGetOssGlobal(hX509OssGlobal);
}
//+-------------------------------------------------------------------------
// 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 OSS formatted info structure
//
// Called by the OssX509*Encode() functions.
//--------------------------------------------------------------------------
static BOOL OssInfoEncode(
IN int pdunum,
IN void *pOssInfo,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
)
{
return OssUtilEncodeInfo(
GetPog(),
pdunum,
pOssInfo,
pbEncoded,
pcbEncoded);
}
//+-------------------------------------------------------------------------
// Decode into an allocated, OSS formatted info structure
//
// Called by the OssX509*Decode() functions.
//--------------------------------------------------------------------------
static BOOL OssInfoDecodeAndAlloc(
IN int pdunum,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
OUT void **ppOssInfo
)
{
return OssUtilDecodeAndAllocInfo(
GetPog(),
pdunum,
pbEncoded,
cbEncoded,
ppOssInfo);
}
//+-------------------------------------------------------------------------
// Free an allocated, OSS formatted info structure
//
// Called by the OssX509*Decode() functions.
//--------------------------------------------------------------------------
static void OssInfoFree(
IN int pdunum,
IN void *pOssInfo
)
{
if (pOssInfo) {
DWORD dwErr = GetLastError();
// TlsGetValue globbers LastError
OssUtilFreeInfo(GetPog(), pdunum, pOssInfo);
SetLastError(dwErr);
}
}
//+-------------------------------------------------------------------------
// OSS X509 v3 ASN.1 Set / Get functions
//
// Called by the OSS 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 OssX509SetObjId(
IN LPSTR pszObjId,
OUT ObjectID *pOss
)
{
pOss->count = sizeof(pOss->value) / sizeof(pOss->value[0]);
if (OssConvToObjectIdentifier(pszObjId, &pOss->count, pOss->value))
return TRUE;
else {
SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
return FALSE;
}
}
static void OssX509GetObjId(
IN ObjectID *pOss,
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;
OssConvFromObjectIdentifier(
pOss->count,
pOss->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 OssX509CtlUsageEncode(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCTL_USAGE pInfo,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
);
static BOOL WINAPI OssX509CtlUsageDecode(
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 OssRequestInfoDecode(
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 OssRequestInfoEncode(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN RequestFlags * pInfo,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
);
static BOOL WINAPI OssCSPProviderEncode(
IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PCRYPT_CSP_PROVIDER pCSPProvider,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
);
static BOOL WINAPI OssNameValueEncode(
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, OssX509CtlUsageEncode,
XENROLL_REQUEST_INFO, OssRequestInfoEncode,
szOID_ENROLLMENT_CSP_PROVIDER, OssCSPProviderEncode,
szOID_ENROLLMENT_NAME_VALUE_PAIR, OssNameValueEncode,
};
#define X509_ENCODE_FUNC_COUNT (sizeof(X509EncodeFuncTable) / \
sizeof(X509EncodeFuncTable[0]))
static const CRYPT_OID_FUNC_ENTRY X509DecodeFuncTable[] = {
X509_ENHANCED_KEY_USAGE, OssX509CtlUsageDecode,
XENROLL_REQUEST_INFO, OssRequestInfoDecode
};
#define X509_DECODE_FUNC_COUNT (sizeof(X509DecodeFuncTable) / \
sizeof(X509DecodeFuncTable[0]))
extern BOOL OssLoad();
extern void OssUnload();
//+-------------------------------------------------------------------------
// Dll initialization
//--------------------------------------------------------------------------
BOOL AsnInit(
HMODULE hInst)
{
if (0 == (hX509OssGlobal = I_CryptInstallOssGlobal(xasn, 0, NULL)))
goto Error;
if (!OssLoad())
goto Error;
if (!CryptInstallOIDFunctionAddress(
hInst,
X509_ASN_ENCODING,
CRYPT_OID_ENCODE_OBJECT_FUNC,
X509_ENCODE_FUNC_COUNT,
X509EncodeFuncTable,
0)) // dwFlags
goto Error;
if (!CryptInstallOIDFunctionAddress(
hInst,
X509_ASN_ENCODING,
CRYPT_OID_DECODE_OBJECT_FUNC,
X509_DECODE_FUNC_COUNT,
X509DecodeFuncTable,
0)) // dwFlags
goto Error;
return TRUE;
Error:
return FALSE;
}
typedef BOOL (WINAPI *PFN_CRYPT_UNINSTALL_OSS_GLOBAL)(
IN HCRYPTOSSGLOBAL hOssGlobal
);
void AsnTerm()
{
HMODULE hDll = NULL;
OssUnload();
hDll = GetModuleHandleA("crypt32.dll");
if (NULL != hDll) {
PFN_CRYPT_UNINSTALL_OSS_GLOBAL pfnCryptUninstallOssGlobal;
pfnCryptUninstallOssGlobal = (PFN_CRYPT_UNINSTALL_OSS_GLOBAL) GetProcAddress(hDll, "I_CryptUninstallOssGlobal");
if (NULL != pfnCryptUninstallOssGlobal) {
pfnCryptUninstallOssGlobal(hX509OssGlobal);
}
}
}
//+-------------------------------------------------------------------------
// OSS X509 v3 ASN.1 Set / Get functions
//
// Called by the OSS 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 OssX509SetCtlUsage(
IN PCTL_USAGE pUsage,
OUT EnhancedKeyUsage *pOss
)
{
DWORD cId;
LPSTR *ppszId;
UsageIdentifier *pOssId;
pOss->count = 0;
pOss->value = NULL;
cId = pUsage->cUsageIdentifier;
if (0 == cId)
return TRUE;
pOssId = (UsageIdentifier *) CertAlloc(cId * sizeof(UsageIdentifier));
if (pOssId == NULL)
return FALSE;
pOss->count = cId;
pOss->value = pOssId;
ppszId = pUsage->rgpszUsageIdentifier;
for ( ; cId > 0; cId--, ppszId++, pOssId++) {
if (!OssX509SetObjId(*ppszId, pOssId))
return FALSE;
}
return TRUE;
}
static void OssX509FreeCtlUsage(
IN EnhancedKeyUsage *pOss)
{
if (pOss->value) {
CertFree(pOss->value);
pOss->value = NULL;
}
}
static void OssX509GetCtlUsage(
IN EnhancedKeyUsage *pOss,
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 *pOssId;
LPSTR *ppszId;
cId = pOss->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;
pOssId = pOss->value;
for ( ; cId > 0; cId--, pOssId++, ppszId++)
OssX509GetObjId(pOssId, dwFlags, ppszId, &pbExtra, &lRemainExtra);
*plRemainExtra = lRemainExtra;
*ppbExtra = pbExtra;
}
//+-------------------------------------------------------------------------
// CTL Usage (Enhanced Key Usage) Encode (OSS X509)
//--------------------------------------------------------------------------
static BOOL WINAPI OssX509CtlUsageEncode(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN PCTL_USAGE pInfo,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
EnhancedKeyUsage OssInfo;
if (!OssX509SetCtlUsage(pInfo, &OssInfo)) {
*pcbEncoded = 0;
fResult = FALSE;
} else
fResult = OssInfoEncode(
EnhancedKeyUsage_PDU,
&OssInfo,
pbEncoded,
pcbEncoded
);
OssX509FreeCtlUsage(&OssInfo);
return fResult;
}
//+-------------------------------------------------------------------------
// CTL Usage (Enhanced Key Usage) Decode (OSS X509)
//--------------------------------------------------------------------------
static BOOL WINAPI OssX509CtlUsageDecode(
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 *pOssInfo = NULL;
BYTE *pbExtra;
LONG lRemainExtra;
if (pInfo == NULL)
*pcbInfo = 0;
if (!OssInfoDecodeAndAlloc(
EnhancedKeyUsage_PDU,
pbEncoded,
cbEncoded,
(void **) &pOssInfo))
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);
OssX509GetCtlUsage(pOssInfo, 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:
OssInfoFree(EnhancedKeyUsage_PDU, pOssInfo);
return fResult;
}
//+-------------------------------------------------------------------------
// Request Info Encode
//--------------------------------------------------------------------------
static BOOL WINAPI OssRequestInfoEncode(
IN DWORD /*dwCertEncodingType*/,
IN LPCSTR /*lpszStructType*/,
IN RequestFlags * pInfo,
OUT BYTE *pbEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
fResult = OssInfoEncode(
RequestFlags_PDU,
pInfo,
pbEncoded,
pcbEncoded
);
return fResult;
}
//+-------------------------------------------------------------------------
// Request Info Decode
//--------------------------------------------------------------------------
static BOOL WINAPI OssRequestInfoDecode(
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 * pOss = NULL;
if (NULL == pInfo || NULL == pcbInfo)
goto ParamError;
if(*pcbInfo < sizeof(RequestFlags))
goto LengthError;
else if (!OssInfoDecodeAndAlloc(
RequestFlags_PDU,
pbEncoded,
cbEncoded,
(void **) &pOss) || NULL == pOss)
goto ErrorReturn;
memcpy(pInfo, pOss, 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 != pOss)
{
OssInfoFree(RequestFlags_PDU, pOss);
}
return fResult;
}
static BOOL WINAPI OssCSPProviderEncode(
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;
OssUtilSetBitString(&pCSPProvider->Signature, &CspProvider.signature.length, &CspProvider.signature.value);
fResult = OssInfoEncode(
CSPProvider_PDU,
&CspProvider,
pbEncoded,
pcbEncoded
);
return fResult;
}
static BOOL WINAPI OssNameValueEncode(
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 = OssInfoEncode(
EnrollmentNameValuePair_PDU,
&NameValue,
pbEncoded,
pcbEncoded
);
return fResult;
}