#ifdef SMIME_V3 #include //#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; icount = 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; iReceiptsFrom.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; icReceiptsTo; 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; ireceiptsFrom.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; ireceiptsTo.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; idwChoice == 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; i1mlReceiptPolicy.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; imailListIdentifier.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; icount; 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; i1mlReceiptPolicy.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; icCategories; 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; isecurity_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); }