Windows2003-3790/inetcore/outlookexpress/inetcomm/ess/essasn.cpp
2020-09-30 16:53:55 +02:00

1992 lines
70 KiB
C++

#ifdef SMIME_V3
#include <windows.h>
//#include "oss\global.hxx"
//#include "oss\ossconv.h"
#include "mimeole.h"
#include "badstrfunctions.h"
extern "C" {
#include "ess.h"
}
#include "essOut.h"
#include "pkiasn1.h"
#include "crypttls.h"
#include "msoert.h"
#include "demand2.h"
#define wcslen my_wcslen
extern int my_wcslen(LPCWSTR pwsz);
//
//
HCRYPTASN1MODULE ICM_hAsn1Module;
typedef struct {
LPSTR szOID;
LPSTR szFunc;
} OIDFunction;
static const OIDFunction EssEncodeExFuncTable[] = {
{szOID_SMIME_Content_Hints, "EssContentHintEncodeEx"},
{szOID_SMIME_Receipt_Request, "EssReceiptRequestEncodeEx"},
{szOID_SMIME_ContentType_Receipt, "EssReceiptEncodeEx"},
{szOID_SMIME_Security_Label, "EssSecurityLabelEncodeEx"},
{szOID_SMIME_MLExpansion_History, "EssMLHistoryEncodeEx"},
{szOID_SMIME_Encryption_Key_Preference, "EssKeyExchPreferenceEncodeEx"},
{szOID_SMIME_Signing_Certificate, "EssSignCertificateEncodeEx"},
};
const int EssEncodeExFuncCount = (sizeof(EssEncodeExFuncTable)/
sizeof(EssEncodeExFuncTable[0]));
static const OIDFunction EssDecodeExFuncTable[] = {
{szOID_SMIME_Content_Hints, "EssContentHintDecodeEx"},
{szOID_SMIME_Receipt_Request, "EssReceiptRequestDecodeEx"},
{szOID_SMIME_ContentType_Receipt, "EssReceiptDecodeEx"},
{szOID_SMIME_Security_Label, "EssSecurityLabelDecodeEx"},
{szOID_SMIME_MLExpansion_History, "EssMLHistoryDecodeEx"},
{szOID_SMIME_Encryption_Key_Preference, "EssKeyExchPreferenceDecodeEx"},
{szOID_SMIME_Signing_Certificate, "EssSignCertificateDecodeEx"},
};
const int EssDecodeExFuncCount = (sizeof(EssDecodeExFuncTable)/
sizeof(EssDecodeExFuncTable[0]));
STDAPI EssRegisterServer(void)
{
HRESULT hr;
int i;
// M00BUG -- need to put in a path for inetcomm.dll!!!!!
for (i=0; i<EssEncodeExFuncCount; i++) {
if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
CRYPT_OID_ENCODE_OBJECT_EX_FUNC,
EssEncodeExFuncTable[i].szOID,
L"inetcomm.dll",
EssEncodeExFuncTable[i].szFunc)) {
goto InstallError;
}
}
for (i=0; i<EssDecodeExFuncCount; i++) {
if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
CRYPT_OID_DECODE_OBJECT_EX_FUNC,
EssDecodeExFuncTable[i].szOID,
L"inetcomm.dll",
EssDecodeExFuncTable[i].szFunc)) {
goto InstallError;
}
}
hr = S_OK;
CommonReturn:
return hr;
InstallError:
hr = E_FAIL;
goto CommonReturn;
}
STDAPI EssUnRegisterServer(void)
{
return S_OK;
}
BOOL WINAPI
EssASNDllMain(HMODULE hInst, ULONG ulReason, LPVOID lpv)
{
BOOL fRet;
switch (ulReason) {
case DLL_PROCESS_ATTACH:
ESS_InitDemandLoadLibs();
break;
case DLL_PROCESS_DETACH:
if (ICM_hAsn1Module != NULL) {
I_CryptUninstallAsn1Module(ICM_hAsn1Module);
ESS_Module_Cleanup();
}
ESS_FreeDemandLoadLibs();
break;
}
fRet = TRUE;
return fRet;
}
#if 0
///////////////////////////////// STOLEN FUNCTIONS ///////////////////////////
//
// The following functions were taken from the wincert.cpp file in the
// ISPU tree. If possible we should get these exported from crypt32.
//
///////////////////////////////////////////////////////////////////////////////
#define INFO_LEN_ALIGN(a) a
//+-------------------------------------------------------------------------
// Set/Get Encoded Object Identifier string
//--------------------------------------------------------------------------
//+-------------------------------------------------------------------------
// Set/Get Object Identifier string
//--------------------------------------------------------------------------
static BOOL OssX509SetObjId(
IN LPCSTR 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;
}
//#define OssX509SetEncodedObjId(pszObjId, pOss) \
// I_CryptSetOssEncodedOID(pszObjId, (OssEncodedOID *) (pOss))
//#define OssX509GetEncodedObjId(pOss, dwFlags, \
// ppszObjId, ppbExtra, plRemainExtra) \
// I_CryptGetOssEncodedOID((OssEncodedOID *) (pOss), dwFlags, \
// ppszObjId, ppbExtra, plRemainExtra)
//+-------------------------------------------------------------------------
// Set/Get "Any" DER BLOB
//--------------------------------------------------------------------------
inline void OssX509SetAny(
IN PCRYPT_OBJID_BLOB pInfo,
OUT NOCOPYANY *pOss
)
{
OssUtilSetAny(pInfo, (OpenType *) pOss);
}
inline void OssX509GetAny(
IN NOCOPYANY *pOss,
IN DWORD dwFlags,
OUT PCRYPT_OBJID_BLOB pInfo,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
OssUtilGetAny((OpenType *) pOss, dwFlags, pInfo, ppbExtra, plRemainExtra);
}
//+-------------------------------------------------------------------------
// Set/Get CRYPT_DATA_BLOB (Octet String)
//--------------------------------------------------------------------------
inline void OssX509SetOctetString(
IN PCRYPT_DATA_BLOB pInfo,
OUT OCTETSTRING *pOss
)
{
pOss->value = pInfo->pbData;
pOss->length = pInfo->cbData;
}
inline void OssX509GetOctetString(
IN OCTETSTRING *pOss,
IN DWORD dwFlags,
OUT PCRYPT_DATA_BLOB pInfo,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
OssUtilGetOctetString(pOss->length, pOss->value, dwFlags,
pInfo, ppbExtra, plRemainExtra);
}
#if 0
//+-------------------------------------------------------------------------
// Set/Free/Get CERT_ALT_NAME_ENTRY
//--------------------------------------------------------------------------
BOOL OssX509SetAltNameEntry(
IN PCERT_ALT_NAME_ENTRY pInfo,
OUT GeneralName *pOss,
IN DWORD dwEntryIndex,
OUT DWORD *pdwErrLocation
)
{
BOOL fResult;
// Assumption: OSS choice == dwAltNameChoice
// OssX509GetAltNameEntry has asserts to verify
pOss->choice = (unsigned short) pInfo->dwAltNameChoice;
*pdwErrLocation = 0;
switch (pInfo->dwAltNameChoice) {
case CERT_ALT_NAME_OTHER_NAME:
if (!OssX509SetEncodedObjId(pInfo->pOtherName->pszObjId,
&pOss->u.otherName.type))
goto ErrorReturn;
OssX509SetAny(&pInfo->pOtherName->Value, &pOss->u.otherName.value);
break;
case CERT_ALT_NAME_DIRECTORY_NAME:
OssX509SetAny(&pInfo->DirectoryName, &pOss->u.directoryName);
break;
case CERT_ALT_NAME_RFC822_NAME:
case CERT_ALT_NAME_DNS_NAME:
case CERT_ALT_NAME_URL:
if (!OssX509SetUnicodeConvertedToIA5(pInfo->pwszRfc822Name,
&pOss->u.rfc822Name, dwEntryIndex, pdwErrLocation))
goto ErrorReturn;
break;
case CERT_ALT_NAME_IP_ADDRESS:
OssX509SetOctetString(&pInfo->IPAddress, &pOss->u.iPAddress);
break;
case CERT_ALT_NAME_REGISTERED_ID:
if (!OssX509SetEncodedObjId(pInfo->pszRegisteredID, &pOss->u.registeredID))
goto ErrorReturn;
break;
case CERT_ALT_NAME_X400_ADDRESS:
case CERT_ALT_NAME_EDI_PARTY_NAME:
default:
SetLastError((DWORD) E_INVALIDARG);
goto ErrorReturn;
}
fResult = TRUE;
CommonReturn:
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
}
void OssX509FreeAltNameEntry(
IN GeneralName *pOss
)
{
switch (pOss->choice) {
case CERT_ALT_NAME_RFC822_NAME:
case CERT_ALT_NAME_DNS_NAME:
case CERT_ALT_NAME_URL:
OssX509FreeUnicodeConvertedToIA5(&pOss->u.rfc822Name);
break;
default:
break;
}
}
BOOL OssX509GetAltNameEntry(
IN GeneralName *pOss,
IN DWORD dwFlags,
OUT PCERT_ALT_NAME_ENTRY pInfo,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
DWORD dwAltNameChoice;
assert(otherName_chosen == CERT_ALT_NAME_OTHER_NAME);
assert(rfc822Name_chosen == CERT_ALT_NAME_RFC822_NAME);
assert(dNSName_chosen == CERT_ALT_NAME_DNS_NAME);
assert(x400Address_chosen == CERT_ALT_NAME_X400_ADDRESS);
assert(directoryName_chosen == CERT_ALT_NAME_DIRECTORY_NAME);
assert(ediPartyName_chosen == CERT_ALT_NAME_EDI_PARTY_NAME);
assert(uniformResourceLocator_chosen == CERT_ALT_NAME_URL);
assert(iPAddress_chosen == CERT_ALT_NAME_IP_ADDRESS);
assert(registeredID_chosen == CERT_ALT_NAME_REGISTERED_ID);
dwAltNameChoice = pOss->choice;
if (*plRemainExtra >= 0)
pInfo->dwAltNameChoice = dwAltNameChoice;
switch (dwAltNameChoice) {
case CERT_ALT_NAME_OTHER_NAME:
{
LONG lAlignExtra;
PCERT_OTHER_NAME pOtherName;
lAlignExtra = INFO_LEN_ALIGN(sizeof(CERT_OTHER_NAME));
*plRemainExtra -= lAlignExtra;
if (*plRemainExtra >= 0) {
pOtherName = (PCERT_OTHER_NAME) *ppbExtra;
pInfo->pOtherName = pOtherName;
*ppbExtra += lAlignExtra;
} else
pOtherName = NULL;
OssX509GetEncodedObjId(&pOss->u.otherName.type, dwFlags,
&pOtherName->pszObjId, ppbExtra, plRemainExtra);
OssX509GetAny(&pOss->u.otherName.value, dwFlags,
&pOtherName->Value, ppbExtra, plRemainExtra);
}
break;
case CERT_ALT_NAME_DIRECTORY_NAME:
OssX509GetAny(&pOss->u.directoryName, dwFlags,
&pInfo->DirectoryName, ppbExtra, plRemainExtra);
break;
case CERT_ALT_NAME_RFC822_NAME:
case CERT_ALT_NAME_DNS_NAME:
case CERT_ALT_NAME_URL:
OssX509GetIA5ConvertedToUnicode(&pOss->u.rfc822Name, dwFlags,
&pInfo->pwszRfc822Name, ppbExtra, plRemainExtra);
break;
case CERT_ALT_NAME_IP_ADDRESS:
OssX509GetOctetString(&pOss->u.iPAddress, dwFlags,
&pInfo->IPAddress, ppbExtra, plRemainExtra);
break;
case CERT_ALT_NAME_REGISTERED_ID:
OssX509GetEncodedObjId(&pOss->u.registeredID, dwFlags,
&pInfo->pszRegisteredID, ppbExtra, plRemainExtra);
break;
case CERT_ALT_NAME_X400_ADDRESS:
case CERT_ALT_NAME_EDI_PARTY_NAME:
break;
default:
SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
return FALSE;
}
return TRUE;
}
//+-------------------------------------------------------------------------
// Set/Free/Get CERT_ALT_NAME_INFO
//--------------------------------------------------------------------------
BOOL OssX509SetAltNames(
IN PCERT_ALT_NAME_INFO pInfo,
OUT AltNames *pOss,
IN DWORD dwIndex,
OUT DWORD *pdwErrLocation
)
{
BOOL fResult;
DWORD i;
DWORD cEntry;
PCERT_ALT_NAME_ENTRY pEntry;
GeneralName *pOssEntry;
*pdwErrLocation = 0;
cEntry = pInfo->cAltEntry;
pEntry = pInfo->rgAltEntry;
pOss->count = cEntry;
pOss->value = NULL;
if (cEntry > 0) {
pOssEntry =
(GeneralName *) PkiZeroAlloc(cEntry * sizeof(GeneralName));
if (pOssEntry == NULL)
goto ErrorReturn;
pOss->value = pOssEntry;
}
// Array of AltName entries
for (i = 0; i < cEntry; i++, pEntry++, pOssEntry++) {
if (!OssX509SetAltNameEntry(pEntry, pOssEntry,
(dwIndex << 8) | i, pdwErrLocation))
goto ErrorReturn;
}
fResult = TRUE;
CommonReturn:
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
}
void OssX509FreeAltNames(
OUT AltNames *pOss
)
{
if (pOss->value) {
DWORD cEntry = pOss->count;
GeneralName *pOssEntry = pOss->value;
for ( ; cEntry > 0; cEntry--, pOssEntry++)
OssX509FreeAltNameEntry(pOssEntry);
PkiFree(pOss->value);
}
}
BOOL OssX509GetAltNames(
IN AltNames *pOss,
IN DWORD dwFlags,
OUT PCERT_ALT_NAME_INFO pInfo,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lAlignExtra;
DWORD cEntry;
PCERT_ALT_NAME_ENTRY pEntry;
GeneralName *pOssEntry;
cEntry = pOss->count;
lAlignExtra = INFO_LEN_ALIGN(cEntry * sizeof(CERT_ALT_NAME_ENTRY));
*plRemainExtra -= lAlignExtra;
if (*plRemainExtra >= 0) {
pInfo->cAltEntry = cEntry;
pEntry = (PCERT_ALT_NAME_ENTRY) *ppbExtra;
pInfo->rgAltEntry = pEntry;
*ppbExtra += lAlignExtra;
} else
pEntry = NULL;
// Array of AltName entries
pOssEntry = pOss->value;
for (; cEntry > 0; cEntry--, pEntry++, pOssEntry++) {
if (!OssX509GetAltNameEntry(pOssEntry, dwFlags,
pEntry, ppbExtra, plRemainExtra))
return FALSE;
}
return TRUE;
}
#endif // 0
//+-------------------------------------------------------------------------
// 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);
}
#endif // 0
//+-------------------------------------------------------------------------
// Function: GetEncoder/GetDecoder
//
// Synopsis: Initialize thread local storage for the asn libs
//
// Returns: pointer to an initialized Asn1 encoder/decoder data
// structures
//--------------------------------------------------------------------------
static inline ASN1encoding_t GetEncoder(void)
{
if (ICM_hAsn1Module == NULL) {
ESS_Module_Startup();
if (0 == (ICM_hAsn1Module = I_CryptInstallAsn1Module(ESS_Module, 0, NULL))) {
return NULL;
}
}
return I_CryptGetAsn1Encoder(ICM_hAsn1Module);
}
static inline ASN1decoding_t GetDecoder(void)
{
if (ICM_hAsn1Module == NULL) {
ESS_Module_Startup();
if (0 == (ICM_hAsn1Module = I_CryptInstallAsn1Module(ESS_Module, 0, NULL))) {
return NULL;
}
}
return I_CryptGetAsn1Decoder(ICM_hAsn1Module);
}
//+-------------------------------------------------------------------------
// Encode an OSS formatted info structure
//
// Called by the OssX509*Encode() functions.
//--------------------------------------------------------------------------
static BOOL OssInfoEncodeEx(
IN int pdunum,
IN void *pvOssInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
return PkiAsn1EncodeInfoEx(GetEncoder(), pdunum, pvOssInfo, dwFlags,
pEncodePara, pvEncoded, pcbEncoded);
}
//+-------------------------------------------------------------------------
// Decode into an OSS 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 OssX509*Decode() functions.
//--------------------------------------------------------------------------
static BOOL OssInfoDecodeAndAllocEx(
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 "Any" DER BLOB
//--------------------------------------------------------------------------
inline void OssX509SetAny(
IN PCRYPT_OBJID_BLOB pInfo,
OUT NOCOPYANY *pOss
)
{
PkiAsn1SetAny(pInfo, pOss);
}
inline void OssX509GetAny(
IN NOCOPYANY *pOss,
IN DWORD dwFlags,
OUT PCRYPT_OBJID_BLOB pInfo,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
PkiAsn1GetAny(pOss, dwFlags, pInfo, ppbExtra, plRemainExtra);
}
//+-------------------------------------------------------------------------
// Set/Get CRYPT_DATA_BLOB (Octet String)
//--------------------------------------------------------------------------
inline void OssX509SetOctetString(
IN PCRYPT_DATA_BLOB pInfo,
OUT OCTETSTRING *pOss
)
{
pOss->value = pInfo->pbData;
pOss->length = pInfo->cbData;
}
inline void OssX509GetOctetString(
IN OCTETSTRING *pOss,
IN DWORD dwFlags,
OUT PCRYPT_DATA_BLOB pInfo,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
PkiAsn1GetOctetString(pOss, dwFlags,
pInfo, ppbExtra, plRemainExtra);
}
#define OssX509SetEncodedObjId(pszObjId, pOss) \
PkiAsn1ToObjectIdentifier(pszObjId, &(pOss)->count, (pOss)->value)
// I_CryptSetEncodedOID(pszObjId, pOss)
#define OssX509GetEncodedObjId(pOss, dwFlags, \
ppszObjId, ppbExtra, plRemainExtra) \
PkiAsn1FromObjectIdentifier((pOss)->count, (pOss)->value, \
ppszObjId, ppbExtra, plRemainExtra)
// I_CryptGetEncodedOID(pOss, dwFlags, \
// ppszObjId, ppbExtra, plRemainExtra)
BOOL
WINAPI
I_CryptSetEncodedOID(
IN LPSTR pszObjId,
OUT ASN1encodedOID_t *pEncodedOid
);
void I_CryptGetEncodedOID(
IN ASN1encodedOID_t *pEncodedOid,
IN DWORD dwFlags,
OUT LPSTR *ppszObjId,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
);
inline BOOL
WINAPI
PkiAsn1SetUTF8String(LPCWSTR pwsz, ASN1wstring_t * pAsn1String)
{
pAsn1String->length = my_wcslen(pwsz);
pAsn1String->value = (LPWSTR) pwsz;
return TRUE;
}
//+-------------------------------------------------------------------------
// Get UTF8 String
//--------------------------------------------------------------------------
void
WINAPI
PkiAsn1GetUTF8String(
IN ASN1wstring_t *putf8String,
IN DWORD dwFlags,
OUT LPWSTR *pwszPrivacyMark,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lRemainExtra = *plRemainExtra;
ULONG ulSize = putf8String->length * sizeof(WCHAR);
lRemainExtra -= (sizeof(WCHAR) + ulSize);
if (lRemainExtra < 0) {
;
}
else {
LPBYTE pbExtra = *ppbExtra;
*pwszPrivacyMark = (LPWSTR) pbExtra;
memcpy(pbExtra, putf8String->value, ulSize);
pbExtra += ulSize;
(* ((LPWSTR) pbExtra) ) = '\0'; // null terminate the wsz.
pbExtra += sizeof(WCHAR);
*ppbExtra = pbExtra;
}
*plRemainExtra = lRemainExtra;
}
#define OssX509GetEncodedUTF8String(putf8String, dwFlags, pwszPrivacyMark, ppbExtra, plRemainExtra) \
PkiAsn1GetUTF8String(putf8String, dwFlags, pwszPrivacyMark, ppbExtra, plRemainExtra)
//+-------------------------------------------------------------------------
// Get PString
//--------------------------------------------------------------------------
void
WINAPI
PkiAsn1GetPString(
IN ASN1ztcharstring_t *pPString,
IN DWORD dwFlags,
OUT LPWSTR *pwszPrivacyMark,
IN OUT BYTE **ppbExtra,
IN OUT LONG *plRemainExtra
)
{
LONG lRemainExtra = *plRemainExtra;
INT cwch = MultiByteToWideChar(CP_ACP, 0, *pPString, -1, NULL, 0);
ULONG ulSize = cwch * sizeof(WCHAR);
if (cwch != 0) {
lRemainExtra -= ulSize;
if (lRemainExtra < 0) {
;
}
else {
*pwszPrivacyMark = (LPWSTR) *ppbExtra;
cwch = MultiByteToWideChar(CP_ACP, 0, *pPString, -1, (LPWSTR) *ppbExtra, cwch);
*ppbExtra += ulSize;
}
*plRemainExtra = lRemainExtra;
}
}
#define OssX509GetEncodedPString(PString, dwFlags, pwszPrivacyMark, ppbExtra, plRemainExtra) \
PkiAsn1GetPString(PString, dwFlags, pwszPrivacyMark, ppbExtra, plRemainExtra)
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// EssContentHintEncodeEx
//
// Description:
// This function is used to encode the ContentHint attribute found in
// some S/MIME messages. Defintion of this object may be found in
// draft-ietf-smime-ess
//
// Parameters:
// dwCertEncodingType - should be ASN_X509_ENCODE
// lpszStructType - should be szOID_Content_Hints
// pInfo - external passed structure with content hints
// dwFlags - control flags
// pEncodePara - allocation functions
// pvEncoded - Return encoded bytes here
// pcbEncoded - Return size of encoded object
//
STDAPI_(BOOL) EssContentHintEncodeEx(IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PSMIME_CONTENT_HINTS pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
ContentHints OssInfo;
memset(&OssInfo, 0, sizeof(OssInfo));
if (pInfo->pszDescription != NULL) {
OssInfo.bit_mask |= contentDescription_present;
OssInfo.contentDescription.length = wcslen(pInfo->pszDescription)*2;
OssInfo.contentDescription.value = pInfo->pszDescription;
}
OssInfo.contentType.count = sizeof(OssInfo.contentType.value)/sizeof(OssInfo.contentType.value[0]);
if (!OssX509SetEncodedObjId(pInfo->pszOIDContent, &OssInfo.contentType)) {
goto ErrorReturn;
}
fResult = OssInfoEncodeEx(ContentHints_PDU, &OssInfo, dwFlags,
pEncodePara, pvEncoded, pcbEncoded);
CommonReturn:
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
*((void **) pvEncoded) = NULL;
}
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
////
STDAPI_(BOOL) EssContentHintDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, LONG *plRemainExtra)
{
LONG lRemainExtra = *plRemainExtra;
LPBYTE pbExtra;
PSMIME_CONTENT_HINTS pInfo = (PSMIME_CONTENT_HINTS) pvStructInfo;
ContentHints * pOssInfo = (ContentHints *) pvOssInfo;
// Remove space of base object
lRemainExtra -= sizeof(SMIME_CONTENT_HINTS);
if (lRemainExtra >= 0) {
pbExtra = (BYTE *) pInfo + sizeof(SMIME_CONTENT_HINTS);
}
else {
pbExtra = NULL;
}
// decode the content-hint description.
if (pOssInfo->bit_mask & contentDescription_present) {
OssX509GetEncodedUTF8String(&pOssInfo->contentDescription, dwFlags,
(pInfo == NULL) ? NULL : &pInfo->pszDescription,
&pbExtra, &lRemainExtra);
}
// decode the content-hint oid.
OssX509GetEncodedObjId(&pOssInfo->contentType, dwFlags, &pInfo->pszOIDContent,
&pbExtra, &lRemainExtra);
*plRemainExtra = lRemainExtra;
return TRUE;
}
//// EssContentHintDecodeEx
//
// Description:
//
// Parameter:
// dwCertEncodingType in -
// lpszStructType in -
// pbEncoded in - ASN encoded structure to be parsed
// cbEncoded in - size of pbEncoded
// dwFlags in -
// pDecodePara in - Allocation parameters
// pvStructInfo out - Returned Content Hints decoded
// pcbStructInfo in/out - sizeof pvStructInfo
//
STDAPI_(BOOL) EssContentHintDecodeEx(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 OssInfoDecodeAndAllocEx(ContentHints_PDU, pbEncoded, cbEncoded,
dwFlags, pDecodePara,
EssContentHintDecodeExCallback, pvStructInfo,
pcbStructInfo);
}
//// EssReceiptRequestEncodeEx
//
// Description:
// This function is used to encode the ReceiptRequest attribute found in
// some S/MIME messages. Defintion of this object may be found in
// draft-ietf-smime-ess
//
// Parameters:
// dwCertEncodingType - should be ASN_X509_ENCODE
// lpszStructType - should be szOID_Content_Hints
// pInfo - external passed structure with content hints
// dwFlags - control flags
// pEncodePara - allocation functions
// pvEncoded - Return encoded bytes here
// pcbEncoded - Return size of encoded object
//
STDAPI_(BOOL) EssReceiptRequestEncodeEx(IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PSMIME_RECEIPT_REQUEST pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
DWORD i;
ReceiptRequest OssInfo;
memset(&OssInfo, 0, sizeof(OssInfo));
// ContentIdentifier
OssInfo.signedContentIdentifier.length = pInfo->ContentIdentifier.cbData;
OssInfo.signedContentIdentifier.value = pInfo->ContentIdentifier.pbData;
// Receipts From
if (pInfo->ReceiptsFrom.cNames > 0) {
OssInfo.receiptsFrom.choice = receiptList_chosen;
OssInfo.receiptsFrom.u.receiptList.count = pInfo->ReceiptsFrom.cNames;
OssInfo.receiptsFrom.u.receiptList.value =
(NOCOPYANY *) malloc(pInfo->ReceiptsFrom.cNames * sizeof(NOCOPYANY));
if (OssInfo.receiptsFrom.u.receiptList.value == NULL) {
goto ErrorReturn;
}
for (i=0; i<pInfo->ReceiptsFrom.cNames; i++) {
OssX509SetAny(&pInfo->ReceiptsFrom.rgNames[i],
&OssInfo.receiptsFrom.u.receiptList.value[i]);
}
}
else {
OssInfo.receiptsFrom.choice = allOrFirstTier_chosen;
OssInfo.receiptsFrom.u.allOrFirstTier = pInfo->ReceiptsFrom.AllOrFirstTier;
}
// Receipts To
OssInfo.receiptsTo.count = (USHORT) pInfo->cReceiptsTo;
OssInfo.receiptsTo.value =
(NOCOPYANY *) malloc(pInfo->cReceiptsTo * sizeof(NOCOPYANY));
if (OssInfo.receiptsTo.value == NULL) {
goto ErrorReturn;
}
for (i=0; i<pInfo->cReceiptsTo; i++) {
OssX509SetAny(&pInfo->rgReceiptsTo[i],
&OssInfo.receiptsTo.value[i]);
}
fResult = OssInfoEncodeEx(ReceiptRequest_PDU, &OssInfo, dwFlags,
pEncodePara, pvEncoded, pcbEncoded);
CommonReturn:
if (OssInfo.receiptsFrom.u.receiptList.value != NULL) {
free(OssInfo.receiptsFrom.u.receiptList.value);
}
if (OssInfo.receiptsTo.value != NULL) {
free(OssInfo.receiptsTo.value);
}
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
*((void **) pvEncoded) = NULL;
}
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
////
STDAPI_(BOOL) EssReceiptRequestDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, LONG *plRemainExtra)
{
DWORD cb;
DWORD i;
LONG lRemainExtra = *plRemainExtra;
LPBYTE pbExtra;
PSMIME_RECEIPT_REQUEST pInfo = (PSMIME_RECEIPT_REQUEST) pvStructInfo;
ReceiptRequest * pOssInfo = (ReceiptRequest *) pvOssInfo;
// Remove space of base object
lRemainExtra -= sizeof(SMIME_RECEIPT_REQUEST);
if (lRemainExtra >= 0) {
pbExtra = (BYTE *) pInfo + sizeof(SMIME_RECEIPT_REQUEST);
memset(pInfo, 0, sizeof(SMIME_RECEIPT_REQUEST));
}
else {
pbExtra = NULL;
pInfo = NULL;
}
//
// ContentIdentifier
//
if (pOssInfo->signedContentIdentifier.length > 0) {
lRemainExtra -= pOssInfo->signedContentIdentifier.length;
if (lRemainExtra >= 0) {
pInfo->ContentIdentifier.cbData =
pOssInfo->signedContentIdentifier.length;
pInfo->ContentIdentifier.pbData = pbExtra;
memcpy(pbExtra, pOssInfo->signedContentIdentifier.value,
pOssInfo->signedContentIdentifier.length);
pbExtra += pOssInfo->signedContentIdentifier.length;
}
}
//
// ReceiptsFrom
//
if (pOssInfo->receiptsFrom.choice == receiptList_chosen) {
cb = pOssInfo->receiptsFrom.u.receiptList.count * sizeof(CERT_NAME_BLOB);
lRemainExtra -= cb;
if (lRemainExtra >= 0) {
pInfo->ReceiptsFrom.cNames = pOssInfo->receiptsFrom.u.receiptList.count;
pInfo->ReceiptsFrom.rgNames = (CERT_NAME_BLOB *) pbExtra;
pbExtra += cb;
}
for (i=0; i<pOssInfo->receiptsFrom.u.receiptList.count; i++) {
OssX509GetAny(&pOssInfo->receiptsFrom.u.receiptList.value[i], dwFlags,
(pInfo == NULL) ? NULL : &pInfo->ReceiptsFrom.rgNames[i],
&pbExtra, &lRemainExtra);
}
}
else {
if (pInfo != NULL) {
pInfo->ReceiptsFrom.AllOrFirstTier =
pOssInfo->receiptsFrom.u.allOrFirstTier;
}
}
// ReceiptsTo
cb = pOssInfo->receiptsTo.count * sizeof(CERT_NAME_BLOB);
lRemainExtra -= cb;
if (lRemainExtra >= 0) {
pInfo->cReceiptsTo = pOssInfo->receiptsTo.count;
pInfo->rgReceiptsTo = (CERT_NAME_BLOB *) pbExtra;
pbExtra += cb;
}
for (i=0; i<pOssInfo->receiptsTo.count; i++) {
OssX509GetAny(&pOssInfo->receiptsTo.value[i], dwFlags,
(pInfo == NULL) ? NULL : &pInfo->rgReceiptsTo[i],
&pbExtra, &lRemainExtra);
}
*plRemainExtra = lRemainExtra;
return TRUE;
}
//// EssReceiptRequestDecodeEx
//
// Description:
//
// Parameter:
// dwCertEncodingType in -
// lpszStructType in -
// pbEncoded in - ASN encoded structure to be parsed
// cbEncoded in - size of pbEncoded
// dwFlags in -
// pDecodePara in - Allocation parameters
// pvStructInfo out - Returned Content Hints decoded
// pcbStructInfo in/out - sizeof pvStructInfo
//
STDAPI_(BOOL) EssReceiptRequestDecodeEx(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 OssInfoDecodeAndAllocEx(ReceiptRequest_PDU, pbEncoded, cbEncoded,
dwFlags, pDecodePara,
EssReceiptRequestDecodeExCallback, pvStructInfo,
pcbStructInfo);
}
////////////////////////////// Receipt Content Type ///////////////////////////////////
//// EssReceiptEncodeEx
//
// Description:
// This function is used to encode the Receipt content type found in
// some S/MIME messages. Defintion of this object may be found in
// draft-ietf-smime-ess
//
// Parameters:
// dwCertEncodingType - should be ASN_X509_ENCODE
// lpszStructType - should be szOID_Content_Hints
// pInfo - external passed structure with content hints
// dwFlags - control flags
// pEncodePara - allocation functions
// pvEncoded - Return encoded bytes here
// pcbEncoded - Return size of encoded object
//
STDAPI_(BOOL) EssReceiptEncodeEx(IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PSMIME_RECEIPT pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
DWORD i;
Receipt OssInfo;
memset(&OssInfo, 0, sizeof(OssInfo));
// Version number
OssInfo.version = pInfo->Version;
// ContentType
OssInfo.contentType.count = sizeof(OssInfo.contentType.value)/sizeof(OssInfo.contentType.value[0]);
fResult = OssX509SetEncodedObjId(pInfo->pszOIDContent, &OssInfo.contentType);
if (!fResult) {
goto ErrorReturn;
}
// ContentIdentifier
OssInfo.signedContentIdentifier.length = pInfo->ContentIdentifier.cbData;
OssInfo.signedContentIdentifier.value = pInfo->ContentIdentifier.pbData;
// Originator signature
OssX509SetOctetString(&pInfo->OriginatorSignature,
&OssInfo.originatorSignatureValue);
// Do the actual encoding
fResult = OssInfoEncodeEx(Receipt_PDU, &OssInfo, dwFlags, pEncodePara,
pvEncoded, pcbEncoded);
CommonReturn:
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
*((void **) pvEncoded) = NULL;
}
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
////
STDAPI_(BOOL) EssReceiptDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, LONG *plRemainExtra)
{
DWORD cb;
DWORD i;
LONG lRemainExtra = *plRemainExtra;
LPBYTE pbExtra;
PSMIME_RECEIPT pInfo = (PSMIME_RECEIPT) pvStructInfo;
Receipt * pOssInfo = (Receipt *) pvOssInfo;
// Remove space of base object
lRemainExtra -= sizeof(SMIME_RECEIPT);
if (lRemainExtra >= 0) {
pbExtra = (BYTE *) pInfo + sizeof(SMIME_RECEIPT);
memset(pInfo, 0, sizeof(SMIME_RECEIPT));
}
else {
pbExtra = NULL;
}
//
// VersionNumber
//
if (pInfo != NULL) {
pInfo->Version = pOssInfo->version;
}
// ContentType
#pragma prefast(suppress:11, "&pInfo->pszOIDContent is OK when pInfo is NULL");
OssX509GetEncodedObjId(&pOssInfo->contentType, dwFlags, &pInfo->pszOIDContent,
&pbExtra, &lRemainExtra);
//
// ContentIdentifier
//
if (pOssInfo->signedContentIdentifier.length > 0) {
lRemainExtra -= pOssInfo->signedContentIdentifier.length;
if (lRemainExtra >= 0) {
pInfo->ContentIdentifier.cbData =
pOssInfo->signedContentIdentifier.length;
pInfo->ContentIdentifier.pbData = pbExtra;
memcpy(pbExtra, pOssInfo->signedContentIdentifier.value,
pOssInfo->signedContentIdentifier.length);
pbExtra += pOssInfo->signedContentIdentifier.length;
}
}
//
// Originator signature
//
#pragma prefast(suppress:11, "&pInfo->OriginatorSignature is OK when pInfo is NULL");
OssX509GetOctetString(&pOssInfo->originatorSignatureValue, dwFlags,
&pInfo->OriginatorSignature, &pbExtra, &lRemainExtra);
*plRemainExtra = lRemainExtra;
return TRUE;
}
//// EssReceiptDecodeEx
//
// Description:
//
// Parameter:
// dwCertEncodingType in -
// lpszStructType in -
// pbEncoded in - ASN encoded structure to be parsed
// cbEncoded in - size of pbEncoded
// dwFlags in -
// pDecodePara in - Allocation parameters
// pvStructInfo out - Returned Content Hints decoded
// pcbStructInfo in/out - sizeof pvStructInfo
//
STDAPI_(BOOL) EssReceiptDecodeEx(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 OssInfoDecodeAndAllocEx(Receipt_PDU, pbEncoded, cbEncoded,
dwFlags, pDecodePara,
EssReceiptDecodeExCallback, pvStructInfo,
pcbStructInfo);
}
////////////////////////////// ML Expansion History /////////////////////////////////
//// EssMLHistoryEncodeEx
//
// Description:
// This function is used to encode the MLHistory content type found in
// some S/MIME messages. Defintion of this object may be found in
// draft-ietf-smime-ess
//
// Parameters:
// dwCertEncodingType - should be ASN_X509_ENCODE
// lpszStructType - should be szOID_Content_Hints
// pInfo - external passed structure with content hints
// dwFlags - control flags
// pEncodePara - allocation functions
// pvEncoded - Return encoded bytes here
// pcbEncoded - Return size of encoded object
//
STDAPI_(BOOL) EssMLHistoryEncodeEx(IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PSMIME_ML_EXPANSION_HISTORY pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
DWORD i;
DWORD i1;
MLExpansionHistory OssInfo;
MLData * pData;
PSMIME_MLDATA pMLData;
memset(&OssInfo, 0, sizeof(OssInfo));
// Move over the count
OssInfo.count = (USHORT) pInfo->cMLData;
pData = OssInfo.value = (MLData *) malloc(OssInfo.count * sizeof(MLData));
if (pData == NULL) {
goto ErrorReturn;
}
memset(OssInfo.value, 0, OssInfo.count*sizeof(MLData));
// Assert(none_chosen == SMIME_MLPOLICY_NONE);
// Assert(insteadOf_chosen == SMIME_MLPOLICY_INSTEAD_OF);
// Assert(inAdditionTo_chosen == SMIME_MLPOLICY_IN_ADDITION_TO);
pMLData = pInfo->rgMLData;
for (i=0; i<OssInfo.count; i++, pData++, pMLData++) {
if (pMLData->dwChoice == SMIME_MLDATA_SUBJECT_KEY_IDENTIFIER) {
pData->mailListIdentifier.choice = subjectKeyIdentifier_chosen;
PkiAsn1SetOctetString(&pMLData->SubjectKeyIdentifier,
&pData->mailListIdentifier.u.subjectKeyIdentifier);
}
else {
pData->mailListIdentifier.choice = EntityIdentifier_issuerAndSerialNumber_chosen;
PkiAsn1SetHugeInteger(&pMLData->u.SerialNumber,
&pData->mailListIdentifier.u.issuerAndSerialNumber.serialNumber);
PkiAsn1SetAny(&pMLData->u.Issuer,
&pData->mailListIdentifier.u.issuerAndSerialNumber.issuer);
}
PkiAsn1ToGeneralizedTime(&pMLData->ExpansionTime, &pData->expansionTime);
if (pMLData->dwPolicy != SMIME_MLPOLICY_NO_CHANGE) {
pData->bit_mask |= mlReceiptPolicy_present;
pData->mlReceiptPolicy.choice = (USHORT) pMLData->dwPolicy;
if (pData->mlReceiptPolicy.choice != SMIME_MLPOLICY_NONE) {
pData->mlReceiptPolicy.u.insteadOf.count = pMLData->cNames;
pData->mlReceiptPolicy.u.insteadOf.value = (GeneralNames *)
malloc(pData->mlReceiptPolicy.u.insteadOf.count * sizeof(GeneralNames));
if (pData->mlReceiptPolicy.u.insteadOf.value == NULL) {
goto ErrorReturn;
}
for (i1=0; i1<pData->mlReceiptPolicy.u.insteadOf.count; i1++) {
OssX509SetAny(&pMLData->rgNames[i1],
&pData->mlReceiptPolicy.u.insteadOf.value[i1]);
}
}
}
}
// Do the actual encoding
fResult = OssInfoEncodeEx(MLExpansionHistory_PDU, &OssInfo, dwFlags, pEncodePara,
pvEncoded, pcbEncoded);
CommonReturn:
if (OssInfo.value != NULL) {
for (pData = OssInfo.value, i=0; i<OssInfo.count; i++, pData++) {
PkiAsn1FreeHugeInteger(pData->mailListIdentifier.u.issuerAndSerialNumber.serialNumber);
if (pData->mlReceiptPolicy.u.insteadOf.value != NULL) {
free(pData->mlReceiptPolicy.u.insteadOf.value);
}
}
free(OssInfo.value);
}
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
*((void **) pvEncoded) = NULL;
}
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
////
STDAPI_(BOOL) EssMLHistoryDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, LONG *plRemainExtra)
{
DWORD cb;
DWORD i;
DWORD i1;
LONG lRemainExtra = *plRemainExtra;
LPBYTE pbExtra;
MLData * pData;
PSMIME_ML_EXPANSION_HISTORY pInfo = (PSMIME_ML_EXPANSION_HISTORY) pvStructInfo;
PSMIME_MLDATA pMLData;
MLExpansionHistory * pOssInfo = (MLExpansionHistory *) pvOssInfo;
// Remove space of base object
lRemainExtra -= sizeof(SMIME_ML_EXPANSION_HISTORY);
if (lRemainExtra >= 0) {
pbExtra = (BYTE *) pInfo + sizeof(SMIME_ML_EXPANSION_HISTORY);
memset(pInfo, 0, sizeof(SMIME_ML_EXPANSION_HISTORY));
}
else {
pbExtra = NULL;
pInfo = NULL;
}
lRemainExtra -= pOssInfo->count * sizeof(SMIME_MLDATA);
if (lRemainExtra >= 0) {
pInfo->cMLData = pOssInfo->count;
pMLData = pInfo->rgMLData = (PSMIME_MLDATA) pbExtra;
pbExtra += pOssInfo->count * sizeof(SMIME_MLDATA);
}
for (i=0, pData = pOssInfo->value; i<pOssInfo->count; i++, pData++) {
if (pData->mailListIdentifier.choice == subjectKeyIdentifier_chosen) {
pData->mailListIdentifier.choice = subjectKeyIdentifier_chosen;
PkiAsn1GetOctetString(&pData->mailListIdentifier.u.subjectKeyIdentifier,
dwFlags, &pMLData->SubjectKeyIdentifier,
&pbExtra, &lRemainExtra);
}
else {
pData->mailListIdentifier.choice = EntityIdentifier_issuerAndSerialNumber_chosen;
PkiAsn1GetHugeInteger(pData->mailListIdentifier.u.issuerAndSerialNumber.serialNumber,
dwFlags, &pMLData->u.SerialNumber,
&pbExtra, &lRemainExtra);
PkiAsn1GetAny(&pData->mailListIdentifier.u.issuerAndSerialNumber.issuer,
dwFlags, &pMLData->u.Issuer,
&pbExtra, &lRemainExtra);
}
if (lRemainExtra >= 0) {
PkiAsn1FromGeneralizedTime(&pData->expansionTime, &pMLData->ExpansionTime);
}
if (pData->bit_mask & mlReceiptPolicy_present) {
if (lRemainExtra >= 0) {
pMLData->dwPolicy = pData->mlReceiptPolicy.choice;
}
if (pData->mlReceiptPolicy.choice != none_chosen) {
lRemainExtra -= pData->mlReceiptPolicy.u.insteadOf.count * sizeof(GeneralNames);
if (lRemainExtra >= 0) {
pMLData->cNames = pData->mlReceiptPolicy.u.insteadOf.count;
pMLData->rgNames = (CERT_NAME_BLOB *) pbExtra;
pbExtra += pMLData->cNames * sizeof(CERT_NAME_BLOB);
}
for (i1=0; i1<pData->mlReceiptPolicy.u.insteadOf.count; i1++) {
OssX509GetAny(&pData->mlReceiptPolicy.u.insteadOf.value[i1],
dwFlags, &pMLData->rgNames[i1], &pbExtra,
&lRemainExtra);
}
}
}
else if (lRemainExtra >= 0) {
pMLData->dwPolicy = SMIME_MLPOLICY_NO_CHANGE;
}
}
*plRemainExtra = lRemainExtra;
return TRUE;
}
//// EssMLHistoryDecodeEx
//
// Description:
//
// Parameter:
// dwCertEncodingType in -
// lpszStructType in -
// pbEncoded in - ASN encoded structure to be parsed
// cbEncoded in - size of pbEncoded
// dwFlags in -
// pDecodePara in - Allocation parameters
// pvStructInfo out - Returned Content Hints decoded
// pcbStructInfo in/out - sizeof pvStructInfo
//
STDAPI_(BOOL) EssMLHistoryDecodeEx(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 OssInfoDecodeAndAllocEx(MLExpansionHistory_PDU, pbEncoded, cbEncoded,
dwFlags, pDecodePara,
EssMLHistoryDecodeExCallback, pvStructInfo,
pcbStructInfo);
}
/////////////////////////////////////////////////////////////////////////////
//// EssSecurityLabelEncodeEx
//
// Description:
// This function is used to encode the SecurityLabel attribute found in
// some S/MIME messages. Defintion of this object may be found in
// draft-ietf-smime-ess
//
// Parameters:
// dwCertEncodingType - should be ASN_X509_ENCODE
// lpszStructType - should be szOID_Security_Label
// pInfo - external passed structure with Security Label
// dwFlags - control flags
// pEncodePara - allocation functions
// pvEncoded - Return encoded bytes here
// pcbEncoded - Return size of encoded object
//
STDAPI_(BOOL) EssSecurityLabelEncodeEx(IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PSMIME_SECURITY_LABEL pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded
)
{
BOOL fResult;
DWORD i;
ESSSecurityLabel OssInfo;
memset(&OssInfo, 0, sizeof(OssInfo));
OssInfo.security_policy_identifier.count = sizeof(OssInfo.security_policy_identifier.value)/sizeof(OssInfo.security_policy_identifier.value[0]);
if (!OssX509SetEncodedObjId(pInfo->pszObjIdSecurityPolicy,
&OssInfo.security_policy_identifier)) {
goto ErrorReturn;
}
if (pInfo->fHasClassification) {
OssInfo.bit_mask |= security_classification_present;
OssInfo.security_classification = (USHORT) pInfo->dwClassification;
}
if (pInfo->wszPrivacyMark != NULL) {
OssInfo.bit_mask |= privacy_mark_present;
OssInfo.privacy_mark.choice = utf8String_chosen;
PkiAsn1SetUTF8String(pInfo->wszPrivacyMark, &OssInfo.privacy_mark.u.utf8String);
}
if (pInfo->cCategories != 0) {
OssInfo.bit_mask |= security_categories_present;
OssInfo.security_categories.count = (USHORT) pInfo->cCategories;
OssInfo.security_categories.value = (SecurityCategory *)
malloc(OssInfo.security_categories.count * sizeof(SecurityCategory));
for (i=0; i<pInfo->cCategories; i++) {
OssInfo.security_categories.value[i].type.count = sizeof(OssInfo.security_categories.value[0].type.value)/sizeof(OssInfo.security_categories.value[0].type.value[0]);
if (!OssX509SetEncodedObjId(pInfo->rgCategories[i].pszObjId,
&OssInfo.security_categories.value[i].type)) {
goto ErrorReturn;
}
OssX509SetAny(&pInfo->rgCategories[i].Value,
&OssInfo.security_categories.value[i].value);
}
}
fResult = OssInfoEncodeEx(ESSSecurityLabel_PDU, &OssInfo, dwFlags,
pEncodePara, pvEncoded, pcbEncoded);
CommonReturn:
if (OssInfo.security_categories.value != NULL) {
free(OssInfo.security_categories.value);
}
return fResult;
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
*((void **) pvEncoded) = NULL;
}
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
////
STDAPI_(BOOL) EssSecurityLabelDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, LONG *plRemainExtra)
{
DWORD cb;
DWORD i;
LONG lRemainExtra = *plRemainExtra;
CRYPT_ATTRIBUTE_TYPE_VALUE * pattr;
LPBYTE pbExtra;
PSMIME_SECURITY_LABEL pInfo = (PSMIME_SECURITY_LABEL) pvStructInfo;
ESSSecurityLabel * pOssInfo = (ESSSecurityLabel *) pvOssInfo;
// Remove space of base object
lRemainExtra -= sizeof(SMIME_SECURITY_LABEL);
if (lRemainExtra >= 0) {
pbExtra = (BYTE *) pInfo + sizeof(SMIME_SECURITY_LABEL);
memset(pInfo, 0, sizeof(*pInfo));
}
else {
pbExtra = NULL;
pInfo = NULL;
}
if (lRemainExtra >= 0) {
pInfo->pszObjIdSecurityPolicy = (LPSTR) pbExtra;
}
OssX509GetEncodedObjId(&pOssInfo->security_policy_identifier, dwFlags,
(pInfo == NULL) ? NULL : &pInfo->pszObjIdSecurityPolicy,
&pbExtra, &lRemainExtra);
if ((pInfo != NULL) &&
(pOssInfo->bit_mask & security_classification_present)) {
pInfo->dwClassification = pOssInfo->security_classification;
pInfo->fHasClassification = TRUE;
}
if (pOssInfo->bit_mask & privacy_mark_present) {
if (utf8String_chosen == pOssInfo->privacy_mark.choice) {
OssX509GetEncodedUTF8String(&pOssInfo->privacy_mark.u.utf8String, dwFlags,
(pInfo == NULL) ? NULL : &pInfo->wszPrivacyMark,
&pbExtra, &lRemainExtra);
}
else if (pString_chosen == pOssInfo->privacy_mark.choice) {
Assert(NULL != pOssInfo->privacy_mark.u.pString);
OssX509GetEncodedPString(&pOssInfo->privacy_mark.u.pString, dwFlags,
(pInfo == NULL) ? NULL : &pInfo->wszPrivacyMark,
&pbExtra, &lRemainExtra);
}
else {
return FALSE; // unknown privacy_mark encoding...
}
}
if (pOssInfo->bit_mask & security_categories_present) {
cb = pOssInfo->security_categories.count *
sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE);
lRemainExtra -= cb;
if (lRemainExtra >= 0) {
pInfo->cCategories = pOssInfo->security_categories.count;
pattr = pInfo->rgCategories = (CRYPT_ATTRIBUTE_TYPE_VALUE *) pbExtra;
pbExtra += cb;
}
else {
pattr = NULL;
}
for (i=0; i<pOssInfo->security_categories.count; i++, pattr++) {
OssX509GetEncodedObjId(&pOssInfo->security_categories.value[i].type,
dwFlags, (pattr == NULL) ? NULL : &pattr->pszObjId,
&pbExtra, &lRemainExtra);
OssX509GetAny(&pOssInfo->security_categories.value[i].value,
dwFlags, (pattr == NULL) ? NULL : &pattr->Value,
&pbExtra, &lRemainExtra);
}
}
*plRemainExtra = lRemainExtra;
return TRUE;
}
//// EssSecurityLabelDecodeEx
//
// Description:
//
// Parameter:
// dwCertEncodingType in -
// lpszStructType in -
// pbEncoded in - ASN encoded structure to be parsed
// cbEncoded in - size of pbEncoded
// dwFlags in -
// pDecodePara in - Allocation parameters
// pvStructInfo out - Returned Security Label decoded
// pcbStructInfo in/out - sizeof pvStructInfo
//
STDAPI_(BOOL) EssSecurityLabelDecodeEx(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 OssInfoDecodeAndAllocEx(ESSSecurityLabel_PDU, pbEncoded, cbEncoded,
dwFlags, pDecodePara,
EssSecurityLabelDecodeExCallback, pvStructInfo,
pcbStructInfo);
}
///////////////////////////////////////////////////////////////////////
BOOL DH_ImportPublicKeyInfoEx(HCRYPTPROV hprov, DWORD dwCertEncodingType,
PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID algId,
DWORD dwFlags,
void * pvAuxInfo, HCRYPTKEY * phKey)
{
DWORD cb;
int cbBlob;
DWORD cbKey;
BOOL fRet = FALSE;
HRESULT hr;
LPBYTE pb;
CRYPT_UINT_BLOB * pblob = NULL;
LPBYTE pbBlob = NULL;
DHPUBKEY * pdhPubKey;
PCERT_DSS_PARAMETERS pDssParameters = NULL;
PUBLICKEYSTRUC * pKeyBlob;
hr = HrDecodeObject(pInfo->Algorithm.Parameters.pbData,
pInfo->Algorithm.Parameters.cbData,
X509_DSS_PARAMETERS, 0, &cb, (LPVOID*) &pDssParameters);
if (FAILED(hr)) {
goto Exit;
}
cbKey = pDssParameters->p.cbData;
if (0 == cbKey) {
goto Exit;
}
cbBlob = sizeof(PUBLICKEYSTRUC) + sizeof(DHPUBKEY) + 3*cbKey;
pbBlob = (LPBYTE) malloc(cbBlob);
pKeyBlob = (PUBLICKEYSTRUC *) pbBlob;
pKeyBlob->bType = PUBLICKEYBLOB;
pKeyBlob->bVersion = CUR_BLOB_VERSION;
pKeyBlob->aiKeyAlg = CALG_DH_EPHEM;
pdhPubKey = (DHPUBKEY *) &pKeyBlob[1];
pdhPubKey->magic = 0x33484400;
pdhPubKey->bitlen = cbKey*8;
pb = (LPBYTE) &pdhPubKey[1];
memcpy(pb, pDssParameters->p.pbData, cbKey);
pb += cbKey;
// memcpy(pb, pDssParameters->q.pbData, pDssParameters->q.cbData);
// pb += pDssParameters->q.cbData;
memcpy(pb, pDssParameters->g.pbData, cbKey);
pb += cbKey;
memcpy(pb, pInfo->PublicKey.pbData, cbKey);
pb += cbKey;
Assert(cbBlob == (pb - pbBlob));
// memcpy(pb, &seed, sizeof(seed));
if (!CryptImportKey(hprov, pbBlob, cbBlob, NULL, 0, phKey)) {
goto Exit;
}
fRet = TRUE;
Exit:
if (pblob != NULL) LocalFree(pblob);
if (pbBlob != NULL) free(pbBlob);
if (pDssParameters != NULL) LocalFree(pDssParameters);
return fRet;
}
#endif // SMIME_V3
////////////////////////////////////////////////////////////////////////////////
//// EssContentHintEncodeEx
//
// Description:
// This function is used to encode the ContentHint attribute found in
// some S/MIME messages. Defintion of this object may be found in
// draft-ietf-smime-ess
//
// Parameters:
// dwCertEncodingType - should be ASN_X509_ENCODE
// lpszStructType - should be szOID_Content_Hints
// pInfo - external passed structure with content hints
// dwFlags - control flags
// pEncodePara - allocation functions
// pvEncoded - Return encoded bytes here
// pcbEncoded - Return size of encoded object
//
STDAPI_(BOOL) EssKeyExchPreferenceEncodeEx(IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PSMIME_ENC_KEY_PREFERENCE pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded)
{
BOOL fResult;
SMIMEEncryptionKeyPreference OssInfo;
memset(&OssInfo, 0, sizeof(OssInfo));
switch (pInfo->RecipientId.dwIdChoice) {
case CERT_ID_ISSUER_SERIAL_NUMBER:
OssInfo.choice = SMIMEEncryptionKeyPreference_issuerAndSerialNumber_chosen;
PkiAsn1SetHugeInteger(&pInfo->RecipientId.IssuerSerialNumber.SerialNumber,
&OssInfo.u.issuerAndSerialNumber.serialNumber);
PkiAsn1SetAny(&pInfo->RecipientId.IssuerSerialNumber.Issuer,
&OssInfo.u.issuerAndSerialNumber.issuer);
break;
case CERT_ID_KEY_IDENTIFIER:
OssInfo.choice = recipientKeyId_chosen;
OssX509SetOctetString(&pInfo->RecipientId.KeyId,
&OssInfo.u.recipientKeyId.subjectKeyIdentifier);
if ((pInfo->Date.dwLowDateTime != 0) || (pInfo->Date.dwHighDateTime != 0)) {
PkiAsn1ToGeneralizedTime(&pInfo->Date, &OssInfo.u.recipientKeyId.date);
}
if (pInfo->pOtherAttr != NULL) {
if (!OssX509SetEncodedObjId(pInfo->pOtherAttr->pszObjId,
&OssInfo.u.recipientKeyId.other.keyAttrId)) {
goto ErrorReturn;
}
if (pInfo->pOtherAttr->Value.cbData != 0) {
OssInfo.u.recipientKeyId.other.bit_mask |= keyAttr_present;
PkiAsn1SetAny(&pInfo->pOtherAttr->Value,
&OssInfo.u.recipientKeyId.other.keyAttr);
}
}
break;
case CERT_ID_SHA1_HASH:
OssInfo.choice = subjectAltKeyIdentifier_chosen;
OssX509SetOctetString(&pInfo->RecipientId.HashId,
&OssInfo.u.subjectAltKeyIdentifier);
break;
default:
goto ErrorReturn;
}
fResult = OssInfoEncodeEx(SMIMEEncryptionKeyPreference_PDU, &OssInfo, dwFlags,
pEncodePara, pvEncoded, pcbEncoded);
CommonReturn:
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
}
STDAPI_(BOOL) EssKeyExchPreferenceDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, LONG *plRemainExtra)
{
LONG lRemainExtra = *plRemainExtra;
LPBYTE pbExtra;
PSMIME_ENC_KEY_PREFERENCE pInfo = (PSMIME_ENC_KEY_PREFERENCE) pvStructInfo;
SMIMEEncryptionKeyPreference * pOssInfo = (SMIMEEncryptionKeyPreference *) pvOssInfo;
// Remove space of base object
lRemainExtra -= sizeof(SMIME_ENC_KEY_PREFERENCE);
if (lRemainExtra >= 0) {
pbExtra = (BYTE *) pInfo + sizeof(SMIME_ENC_KEY_PREFERENCE);
}
else {
pbExtra = NULL;
}
switch (pOssInfo->choice) {
case SMIMEEncryptionKeyPreference_issuerAndSerialNumber_chosen:
if (pInfo != NULL) {
pInfo->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
}
PkiAsn1GetHugeInteger(pOssInfo->u.issuerAndSerialNumber.serialNumber,
dwFlags, (pInfo == NULL) ? NULL :
&pInfo->RecipientId.IssuerSerialNumber.SerialNumber,
&pbExtra, &lRemainExtra);
PkiAsn1GetAny(&pOssInfo->u.issuerAndSerialNumber.issuer, dwFlags,
(pInfo == NULL) ? NULL :
&pInfo->RecipientId.IssuerSerialNumber.Issuer,
&pbExtra, &lRemainExtra);
break;
case recipientKeyId_chosen:
if (pInfo != NULL) {
pInfo->RecipientId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
}
OssX509GetOctetString(&pOssInfo->u.recipientKeyId.subjectKeyIdentifier,
dwFlags, &pInfo->RecipientId.KeyId,
&pbExtra, &lRemainExtra);
if ((lRemainExtra >= 0) &&
(pOssInfo->u.recipientKeyId.bit_mask & date_present)) {
PkiAsn1FromGeneralizedTime(&pOssInfo->u.recipientKeyId.date,
&pInfo->Date);
}
if (pOssInfo->u.recipientKeyId.bit_mask & other_present) {
OssX509GetEncodedObjId(&pOssInfo->u.recipientKeyId.other.keyAttrId,
dwFlags, (pInfo == NULL) ? NULL :
&pInfo->pOtherAttr->pszObjId,
&pbExtra, &lRemainExtra);
if (pOssInfo->u.recipientKeyId.other.bit_mask & keyAttr_present) {
PkiAsn1GetAny(&pOssInfo->u.recipientKeyId.other.keyAttr,
dwFlags, (pInfo == NULL) ? NULL :
&pInfo->pOtherAttr->Value, &pbExtra, &lRemainExtra);
}
}
break;
case subjectAltKeyIdentifier_chosen:
if (pInfo != NULL) {
pInfo->RecipientId.dwIdChoice = CERT_ID_SHA1_HASH;
}
OssX509GetOctetString(&pOssInfo->u.subjectAltKeyIdentifier, dwFlags,
&pInfo->RecipientId.HashId, &pbExtra, &lRemainExtra);
break;
default:
return FALSE;
}
*plRemainExtra = lRemainExtra;
return TRUE;
}
//// EssKeyExchPreferenceDecodeEx
//
// Description:
//
// Parameter:
// dwCertEncodingType in -
// lpszStructType in -
// pbEncoded in - ASN encoded structure to be parsed
// cbEncoded in - size of pbEncoded
// dwFlags in -
// pDecodePara in - Allocation parameters
// pvStructInfo out - Returned Content Hints decoded
// pcbStructInfo in/out - sizeof pvStructInfo
//
STDAPI_(BOOL) EssKeyExchPreferenceDecodeEx(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 OssInfoDecodeAndAllocEx(SMIMEEncryptionKeyPreference_PDU, pbEncoded,
cbEncoded, dwFlags, pDecodePara,
EssKeyExchPreferenceDecodeExCallback,
pvStructInfo, pcbStructInfo);
}
//// EssSignCertificateEncodeEx
//
// Description:
// This function is used to encode the ContentHint attribute found in
// some S/MIME messages. Defintion of this object may be found in
// draft-ietf-smime-ess
//
// Parameters:
// dwCertEncodingType - should be ASN_X509_ENCODE
// lpszStructType - should be szOID_Content_Hints
// pInfo - external passed structure with content hints
// dwFlags - control flags
// pEncodePara - allocation functions
// pvEncoded - Return encoded bytes here
// pcbEncoded - Return size of encoded object
//
STDAPI_(BOOL) EssSignCertificateEncodeEx(IN DWORD dwCertEncodingType,
IN LPCSTR lpszStructType,
IN PSMIME_SIGNING_CERTIFICATE pInfo,
IN DWORD dwFlags,
IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
OUT OPTIONAL void *pvEncoded,
IN OUT DWORD *pcbEncoded)
{
BOOL fResult;
SigningCertificate OssInfo;
memset(&OssInfo, 0, sizeof(OssInfo));
fResult = OssInfoEncodeEx(SigningCertificate_PDU, &OssInfo, dwFlags,
pEncodePara, pvEncoded, pcbEncoded);
//CommonReturn:
return fResult;
#if 0
ErrorReturn:
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
*((void **) pvEncoded) = NULL;
}
*pcbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
#endif // 0
}
STDAPI_(BOOL) EssSignCertificateDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, LONG *plRemainExtra)
{
LONG lRemainExtra = *plRemainExtra;
LPBYTE pbExtra;
PSMIME_CONTENT_HINTS pInfo = (PSMIME_CONTENT_HINTS) pvStructInfo;
ContentHints * pOssInfo = (ContentHints *) pvOssInfo;
// Remove space of base object
lRemainExtra -= sizeof(SMIME_CONTENT_HINTS);
if (lRemainExtra >= 0) {
pbExtra = (BYTE *) pInfo + sizeof(SMIME_CONTENT_HINTS);
}
else {
pbExtra = NULL;
}
OssX509GetEncodedObjId(&pOssInfo->contentType, dwFlags, &pInfo->pszOIDContent,
&pbExtra, &lRemainExtra);
*plRemainExtra = lRemainExtra;
return TRUE;
}
//// EssSignCertificateDecodeEx
//
// Description:
//
// Parameter:
// dwCertEncodingType in -
// lpszStructType in -
// pbEncoded in - ASN encoded structure to be parsed
// cbEncoded in - size of pbEncoded
// dwFlags in -
// pDecodePara in - Allocation parameters
// pvStructInfo out - Returned Content Hints decoded
// pcbStructInfo in/out - sizeof pvStructInfo
//
STDAPI_(BOOL) EssSignCertificateDecodeEx(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 OssInfoDecodeAndAllocEx(SigningCertificate_PDU, pbEncoded, cbEncoded,
dwFlags, pDecodePara,
EssSignCertificateDecodeExCallback, pvStructInfo,
pcbStructInfo);
}