The CryptMsgOpenToDecode function opens a cryptographic message for decoding. The message remains open until CryptMsgClose is called.
Important changes have been made to the CryptoAPI in order to support S/MIME e-mail interoperability, which affect the handling of enveloped messages. See the Remarks for CryptMsgOpenToEncode for details.
#include <wincrypt.h>
HCRYPTMSG WINAPI CryptMsgOpenToDecode(
DWORD dwMsgEncodingType, // in
DWORD dwFlags, // in
DWORD dwMsgType, // in
HCRYPTPROV hCryptProv, // in
PCERT_INFO pRecipientInfo, // in/optional
PCMSG_STREAM_INFO pStreamInfo // in/optional
);
CRYPT_ASN_ENCODING | PKCS_7_ASN_ENCODING
However, it is required only to specify the message encoding here. Currently defined encoding types are shown in the following table.
Encoding type | Value |
---|---|
CRYPT_ASN_ENCODING | 0x00000001 |
PKCS_7_ASN_ENCODING | 0x00010000 |
Message type | Associated structures | Value |
---|---|---|
CMSG_DATA | Raw data (no associated structure) | 1 |
CMSG_ENCRYPTED | Not implemented. | 6 |
CMSG_ENVELOPED | CMSG_ENVELOPED_ENCODE_INFO | 3 |
CMSG_HASHED | CMSG_HASHED_ENCODE_INFO | 5 |
CMSG_SIGNED | CMSG_SIGNER_ENCODE_INFO, CMSG_SIGNED_ENCODE_INFO | 2 |
CMSG_SIGNED_AND_ENVELOPED | Not implemented. | 4 |
For the Message type descriptions, see CryptMsgOpenToEncode.
Signed messages created with Microsoft® Internet Explorer version 3.0 do not contain header information. To maintain compatibility with Internet Explorer version 3.0, the dwMsgType parameter is provided. Therefore, if a signed message from Internet Explorer version 3.0 is received, the message type must be passed in to the function.
When zero is passed in for the dwMsgType parameter, this function will attempt to read the message type from the header on the message. If the header is missing, as in the case of some Internet Explorer version 3.0 messages, the function call will fail.
Unless there is a strong reason for passing in a specific cryptographic provider in hCryptProv, zero should be passed in. Passing in zero causes the default RSA or DSS provider to be acquired before doing hash, signature verification or recipient encryption operations.
When streaming is being used, this parameter should point to a CMSG_STREAM_INFO structure. The callback specified by pfnStreamOutput in the CMSG_STREAM_INFO structure is called when CryptMsgUpdate is executed (and also when CryptMsgControl is executed when decoding a streamed enveloped message). For more information on how to use the callback, see CMSG_STREAM_INFO.
For a signed message, the callback is passed a block of the decoded bytes from the inner content of the message.
For an enveloped message, periodic checks should be made to see if the CMSG_ENVELOPE_ALGORITHM_PARAM is available yet by calling CryptMsgGetParam (CMSG_ENVELOPE_ALGORITHM_PARAM after each call to CryptMsgUpdate. CryptMsgGetParam will fail with LastError == CRYPT_E_STREAM_MSG_NOT_READY until enough of the message has been processed by CryptMsgUpdate to make the CMSG_ENVELOPE_ALGORITHM_PARAM available. Once it is available, the application can then iterate through the recipients, retrieving the CERT_INFO for each using CryptMsgGetParam (CMSG_RECIPIENT_INFO_PARAM).
The CERT_INFO for a recipient is used to call CertGetSubjectCertificateFromStore to see if a matching certificate is in the "my" certificate store (CertOpenSystemStore or CertOpenStore must have been previously called to open the "my" store). When a match is found, CertGetCertificateContextProperty(CERT_KEY_PROV_INFO_PROP_ID) is called which returns a CRYPT_KEY_PROV_INFO structure that contains the information necessary to acquire the private key for that recipient. CryptAcquireContext is called using the pwszContainerName, pwszProvName, dwProvType, and dwFlags members of CRYPT_KEY_PROV_INFO as parameters to get the desired hCryptProv. This hCryptProv and the dwKeySpec from the CRYPT_KEY_PROV_INFO are passed to CryptMsgControl (as a member of the CMSG_CTRL_DECRYPT_PARA structure) to permit the start of the decryption of the inner content. The streaming code will then perform the decryption as the data is input, and the resulting blocks of plaintext gets passed to the callback specified by pfnStreamOutput where an application may save it to a file.
Note The streaming decode for an enveloped message queues up the ciphertext in memory until CryptMsgControl is called to start the decryption. It is up to the application to initiate decrypting in a timely manner so that the data can be saved to disk (or routed elsewhere) before the accumulated ciphertext becomes too large and the system runs out of memory.
Consider the case of a signed message enclosed in an enveloped message. The plaintext output from the streaming decode of the enveloped message can be fed into another streaming decode which can process the signed message.
Returns a handle to the opened message if successful. Returns NULL if the operation failed.
To retrieve extended error information, use the GetLastError function.
The following table lists the error codes most commonly returned by the GetLastError function.
Error code | Description |
---|---|
E_INVALIDARG | One or more arguments are invalid. |
E_OUTOFMEMORY | Ran out of memory. |
See Signed Message Example Code.
See Enveloped Message Example 1.
See Hashed Message Example Code.
Windows NT: Requires version 4.0 SP3 or later. Available also in IE 3.02 and later.
Windows: Requires Windows 98 (or Windows 95 with IE 3.02 or later).
Windows CE: Unsupported.
Header: Declared in wincrypt.h.
Import Library: Use crypt32.lib.
CryptMsgClose, CryptMsgUpdate, CryptMsgGetParam, CryptMsgOpenToEncode