/* ** 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 #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