1992 lines
70 KiB
C++
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);
|
|
}
|
|
|