|
|
/*
** s m i m e . h ** ** Purpose: class for cryptographically enhanced mail. ** ** Owner: t-erikne ** Created: 8/27/96 ** ** Copyright (C) Microsoft Corp. 1996-1998 */
#ifndef __SMIME_H
#define __SMIME_H
#include <mimeole.h>
#ifndef __WINCRYPT_H__
#include "wincrypt.h"
#endif
#ifdef SMIME_V3
// #include "..\ess\essout.h"
#endif // SMIME_V3
#define szOID_INFOSEC_keyExchangeAlgorithm "2.16.840.1.101.2.1.1.22"
#include "capitype.h"
#include "cryptdbg.h"
// WinCrypt.h helper
#define DOUTL_SMIME CRYPT_LEVEL
class CCAPIStm;
extern CRYPT_ENCODE_PARA CryptEncodeAlloc; extern CRYPT_DECODE_PARA CryptDecodeAlloc;
#ifdef MAC
/*
** An array of function pointers, needed because we dynalink to ** CRYPT32.DLL. Note that not all of the crypto functions come ** from this DLL. I also use functions from ADVAPI32: the CAPI 1 ** functions. These are not represented in this table and do not ** need to use GetProcAddress. ** Typedefs come from capitype.h, local to our project. */
typedef struct tagCAPIfuncs { CERTENUMCERTIFICATESINSTORE *EnumCerts; CERTNAMETOSTRA *CertNameToStr; } CAPIfuncs, *PCAPIfuncs; #endif // MAC
/////////////////////////////////////////////////////////////////////////////
//
// Structure definitions
//
typedef enum { ENCRYPT_ITEM_TRANSPORT = 1, ENCRYPT_ITEM_AGREEMENT = 2, ENCRYPT_ITEM_MAILLIST = 3 } ENCRYPT_ITEM_TYPE;
typedef struct tagEncryptItem { DWORD dwTagType; union { struct { BLOB blobAlg; DWORD cCert; PCCERT_CONTEXT * rgpccert; } Transport; struct { BLOB blobAlg; DWORD cCert; PCCERT_CONTEXT * rgpccert; PCCERT_CONTEXT pccertSender; } Agreement; struct { BLOB blobAlg; // AlgId + AuxInfo
BLOB blobKeyId; // Data_Blob KeyID
FILETIME date; // Date
BLOB blobOctet; // Other attribute (oid, any)
#ifdef SMIME_V3
HCRYPTPROV hprov; // hprov
HCRYPTKEY hkey; // hkey
#else // !SMIME_V3
BLOB blobKeyMaterial; #endif // SMIME_V3
} MailList; }; } EncryptItem;
typedef struct tagEncryptItems { DWORD cItems; EncryptItem * rgItems; } EncryptItems;
//
// Notes about the [directions]
// [sgn] - signing -- in for sign ops
// [ver] - verification -- out for sign ops
// [enc] - encryption -- in for encrypt ops
// [dec] - decryption -- out for encrypt ops
// [in] = [sgn,enc]
// [out] = [ver,dec]
//
typedef struct { DWORD ulValidity; // Validity bits for each signature
PCCERT_CONTEXT pccert; // Signer certificate
BLOB blobHashAlg; // Hash algorithm for signer
BLOB blobAuth; // authenticated attributes
BLOB blobUnauth; // unauthenticated attributes
#ifdef SMIME_V3
BLOB blobReceipt; // Receipt to be returned
BLOB blobHash; // Hash of message
#endif // SMIME_V3
} SignerData;
class CSECURITY_LAYER_DATA : public IUnknown { friend class CSMime; // Allow CSMime access to our private data
friend class CCAPIStm; // Allow CCAPIStm access to our private data
public: CSECURITY_LAYER_DATA(void); ~CSECURITY_LAYER_DATA(void);
// --------------------------------------------------------------------
// IUnknown
// --------------------------------------------------------------------
STDMETHODIMP QueryInterface(REFIID, LPVOID *); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void);
//private: // private data
DWORD m_cRef; DWORD m_dwMsgEnhancement; // sign? encrypt?
BOOL m_fCertInLayer; // TRUE if there is a cert included in this layer
// The following elements exist one for each signer on the current layer
DWORD m_cSigners; // Count of signers
SignerData * m_rgSigners; // Signer Data
// The following items exist to encrypt the current layer
DWORD m_cEncryptItems; // Encrypt Item count
#ifdef SMIME_V3
CRYPT_ALGORITHM_IDENTIFIER m_ContentEncryptAlgorithm; // Content AlgId
void * m_pvEncryptAuxInfo; // Aux info
CMSG_RECIPIENT_ENCODE_INFO * m_rgRecipientInfo; // Array of Recpient Infos
CRYPT_DATA_BLOB m_blobUnprotectAttrs; // Unprotected attributes
HCERTSTORE m_hstoreEncrypt; // Encrypt cert store
#else // !SMIME_V3
EncryptItem * m_rgEncryptItems; // count of Encrypt Items
#endif // SMIME_V3
// The following items exists for a decrypted message
DWORD m_ulDecValidity; BLOB m_blobDecAlg; // Decryption Algorithm
PCCERT_CONTEXT m_pccertDecrypt; // Decryption Certificate
// These are items common to both encryption and signing
HCERTSTORE m_hcertstor; // message cert store
// Cert Bag for signing
// Originator Info for encryption
//
CSECURITY_LAYER_DATA * m_psldInner; // down link
CSECURITY_LAYER_DATA * m_psldOuter; // up link
}; typedef class CSECURITY_LAYER_DATA SECURITY_LAYER_DATA; typedef SECURITY_LAYER_DATA * PSECURITY_LAYER_DATA;
// -------------------------------------------------------------------
// SMIMEINFO:
// bidirectional communication struct for passing parameter
// info to/from the en/decode functions
//
// dwMsgEnhancement [inout]
// fCertWithMsg [ver]
// ulMsgValidity [out]
// ietRequested [in]
// -------------------------------------------------------------------
struct SMIMEINFOtag { // si
DWORD dwMsgEnhancement; PSECURITY_LAYER_DATA psldLayers; // outermost layer
PSECURITY_LAYER_DATA psldEncrypt; // encryption layer
PSECURITY_LAYER_DATA psldInner; // innermost layer
ULONG cStores; // size of rgStores
HCERTSTORE * rgStores; // array of cert stores
BOOL fCertWithMsg; ULONG ulMsgValidity; ENCODINGTYPE ietRequested; HCRYPTPROV hProv; #ifdef SMIME_V3
LPSTR pszInnerContent; // Inner content (NULL ->> id-data)
DWORD cbInnerContent; // Inner content size if != id-data
LPWSTR pwszKeyPrompt; // Key password prompt
#endif // SMIME_V3
}; typedef struct SMIMEINFOtag SMIMEINFO; typedef SMIMEINFO *PSMIMEINFO; typedef const SMIMEINFO *PCSMIMEINFO;
/////////////////////////////////////////////////////////////////////////////
//
// Class begins
//
class CSMime : public IMimeSecurity { public: //
// ctor and dtor
//
CSMime(void); ~CSMime();
//
// IUnknown methods
//
STDMETHODIMP QueryInterface(REFIID, LPVOID *); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void);
//
// IMimeSecurity methods
//
STDMETHODIMP InitNew(); STDMETHODIMP CheckInit();
STDMETHODIMP EncodeMessage(IMimeMessageTree *const pTree, DWORD dwFlags); STDMETHODIMP DecodeMessage(IMimeMessageTree *const pTree, DWORD dwFlags); STDMETHODIMP EncodeBody(IMimeMessageTree *const pTree, HBODY hEncodeRoot, DWORD dwFlags); STDMETHODIMP DecodeBody(IMimeMessageTree *const pTree, HBODY hDecodeRoot, DWORD dwFlags);
STDMETHODIMP EnumCertificates(HCAPICERTSTORE hc, DWORD dwUsage, PCX509CERT pPrev, PCX509CERT *pCert); STDMETHODIMP GetCertificateName(const PCX509CERT pX509Cert, const CERTNAMETYPE cn, LPSTR *ppszName); STDMETHODIMP GetMessageType(const HWND hwndParent, IMimeBody *const pBody, DWORD *const pdwSecType);
STDMETHODIMP GetCertData(const PCX509CERT pX509Cert, const CERTDATAID dataid, LPPROPVARIANT pValue);
// Other methods
HRESULT EncodeMessage2(IMimeMessageTree * const pTree, DWORD dwFlags, HWND hwnd); HRESULT DecodeMessage2(IMimeMessageTree * const pTree, DWORD dwFlags, HWND hwnd, IMimeSecurityCallback * pCallback); HRESULT EncodeBody2(IMimeMessageTree *const pTree, HBODY hEncodeRoot, DWORD dwFlags, HWND hwnd); HRESULT DecodeBody2(IMimeMessageTree *const pTree, HBODY hDecodeRoot, DWORD dwFlags, SMIMEINFO * psiOuterOp, HWND hwnd, IMimeSecurityCallback * pCallback);
//
// Implementation methods
//
static void UnloadAll(void); static HRESULT HrGetCertsFromThumbprints(THUMBBLOB *const rgThumbprint, X509CERTRESULT *const pResults); static HRESULT StaticGetMessageType(HWND hwndParent, IMimeBody *const pBody, DWORD *const pdwSecType);
protected: static HRESULT StaticCheckInit();
struct CERTARRAY { DWORD cCerts; PCCERT_CONTEXT *rgpCerts; }; typedef CERTARRAY *PCERTARRAY; typedef const CERTARRAY *PCCERTARRAY;
HRESULT DecodeBody (IMimeMessageTree *const pTree, HBODY hDecodeRoot, DWORD dwFlags, SMIMEINFO * psiOuterOp);
HRESULT HrEncodeOpaque (SMIMEINFO *const psi, IMimeMessageTree *pTree, HBODY hEncodeRoot, IMimeBody *pEncodeRoot, LPSTREAM lpstmOut, HWND hwnd); HRESULT HrDecodeOpaque (DWORD dwFlags, SMIMEINFO *const psi, IMimeBody *const pBody, IStream *const pstmOut, HWND hwnd, IMimeSecurityCallback * pCallback); HRESULT HrEncodeClearSigned (SMIMEINFO *const psi, IMimeMessageTree *const pTree, const HBODY hEncodeRoot, IMimeBody *const pEncodeRoot, LPSTREAM lpstmOut, BOOL fCommit, HWND hwnd); HRESULT HrDecodeClearSigned (DWORD dwFlags, SMIMEINFO *const psi, IMimeMessageTree *const pTree, const HBODY hData, const HBODY hSig, HWND hwnd, IMimeSecurityCallback * pCallback);
static BOOL FSign(const DWORD dwAction) { return BOOL(dwAction & MST_SIGN_MASK); } static BOOL FClearSign(const DWORD dwAction) { return (FSign(dwAction) && !(dwAction & MST_BLOB_FLAG)); } static BOOL FEncrypt(const DWORD dwAction) { return BOOL(dwAction & MST_ENCRYPT_MASK); }
static HRESULT HrGetNeededAddresses(const DWORD dwTypes, IMimeMessageTree *pTree, IMimeAddressTable **ppAdrTable, IMimeEnumAddressTypes **ppEnum); static HRESULT HrGetCertificates(IMimeAddressTable *const pAdrTable, IMimeEnumAddressTypes *pEnum, const DWORD dwType, const BOOL fAlreadyHaveSendersCert, CERTARRAY *rgCerts); static HRESULT HrGetThumbprints(IMimeEnumAddressTypes *pEnum, const ITHUMBPRINTTYPE ittType, THUMBBLOB *const rgThumbprint); static HRESULT HrGenerateCertsStatus(X509CERTRESULT *pResults, IMimeAddressTable *const pAdrTable, IMimeEnumAddressTypes *const pEnum, const BOOL fIgnoreSenderError);
HRESULT HrFindUsableCert(HCERTSTORE hCertStore, BYTE dwKeySpec, PCCERT_CONTEXT pPrevCert, PCCERT_CONTEXT *ppCert);
static HRESULT OptionsToSMIMEINFO(BOOL fEncode, IMimeMessageTree *const pmm, IMimeBody *pBody, SMIMEINFO *psi); static HRESULT SMIMEINFOToOptions(IMimeMessageTree *const pTree, const SMIMEINFO *psi, HBODY hBody); static HRESULT MergeSMIMEINFO( SMIMEINFO * psiOut, SMIMEINFO * psiInner); static void FreeSMIMEINFO(SMIMEINFO *psi);
#ifdef DEBUG
void DumpAlgorithms(); #endif
private: static HRESULT HrInitCAPI(); static void UnloadCAPI();
static HRESULT CAPISTMtoSMIMEINFO(CCAPIStm *pcapistm, SMIMEINFO *psi); static void MergeSMIMEINFOs(const SMIMEINFO *const psiOuter, SMIMEINFO *const psiInner);
UINT m_cRef; CRITICAL_SECTION m_cs; #ifdef MAC
static CAPIfuncs ms_CAPI; static LPCSTR ms_rgszFuncNames[]; #endif // MAC
};
inline BOOL IsOpaqueSecureContentType(IMimePropertySet *pSet) { return ( S_OK == pSet->IsContentType(STR_CNT_APPLICATION, STR_SUB_XPKCS7MIME) || S_OK == pSet->IsContentType(STR_CNT_APPLICATION, STR_SUB_PKCS7MIME)); }
inline BOOL IsSecureContentType(IMimePropertySet *pSet) { return ( S_OK == pSet->IsContentType(STR_CNT_MULTIPART, STR_SUB_SIGNED) || IsOpaqueSecureContentType(pSet)); }
BOOL IsSMimeProtocol(LPMIMEPROPERTYSET lpPropSet);
#ifdef SMIME_V3
void FreeRecipientInfoContent(PCMS_RECIPIENT_INFO pRecipInfo); HRESULT HrCopyOID(LPCSTR psz, LPSTR * ppsz); HRESULT HrCopyCryptDataBlob(const CRYPT_DATA_BLOB * pblobSrc, PCRYPT_DATA_BLOB pblobDst); HRESULT HrCopyCryptBitBlob(const CRYPT_BIT_BLOB * pblobSrc, PCRYPT_BIT_BLOB pblobDst); HRESULT HrCopyCryptAlgorithm(const CRYPT_ALGORITHM_IDENTIFIER * pAlgSrc, PCRYPT_ALGORITHM_IDENTIFIER pAlgDst); HRESULT HrCopyCertId(const CERT_ID * pcertidSrc, PCERT_ID pcertidDst); #endif // SMIME_V3
#endif // _SMIME_H
|