Benoit
Benoit

Reputation: 79243

CryptVerifyMessageSignature returns original message with an additional header, why?

I have used signtool to produce a PKCS#7 bundle that contains:

The command that builds this PKCS#7 file is the following:

$signtool sign /f signer_certificate.pfx /p ∙∙∙ /fd sha512 /p7 . /p7ce Embedded /p7co 0 my_file

This outputs a file named my_file.p7 in DER form (ASN.1).

Now I wrote a C++ program to verify that, from the bundle, we can extract both the certificate and the message. For this I call CryptVerifyMessageSignature:

#include <windows.h>
#include <wincrypt.h>
#include <vector>

std::vector<BYTE> InputPkcs7Data;
// read input file into InputPkcs7Data (CreateFile, GetFileSizeEx, ReadFile).
// out of scope.

CRYPT_VERIFY_MESSAGE_PARA Parameters = {};
Parameters.cbSize = sizeof(Parameters);
Parameters.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
Parameters.hCryptProv = NULL;
Parameters.pfnGetSignerCertificate = NULL;
Parameters.pvGetArg = NULL;

DWORD DecodedMessageLength = 0;
PCCERT_CONTEXT SignerCertificate = NULL;
BOOL Result = CryptVerifyMessageSignature(&Parameters, 0, InputPkcs7Data.data(), InputPkcs7Data.size(), NULL, &DecodedMessageLength, &SignerCertificate);

std::vector<BYTE> DecodedMessage;
DecodedMessage.assign(DecodedMessageLength, 0);

Result = CryptVerifyMessageSignature(&Parameters, 0, InputPkcs7Data.data(), InputPkcs7Data.size(), DecodedMessage.data(), &DecodedMessageLength, &SignerCertificate);

if (Result == FALSE) {
    wprintf(L"Error: %lx\n", GetLastError());
}
else
{
    // inspect Memory
    CertFreeCertificateContext(SignerCertificate);
}

My problem here is that, even if CryptVerifyMessageSignature succeeds, What I get into DecodedMessage is not the original message. There are always several leading bytes that seem like garbage at first, but that contain information about the message length. I managed to understand that DecodedMessage is sequenced as follows, depending on the length of original message:

This is really unexpected to me. Where does this “header information” stem from, and is there a way I can avoid getting it when calling CryptVerifyCertificate?

Is it possible that signtool is not the right tool for generating the signed message?

Upvotes: 0

Views: 313

Answers (1)

Benoit
Benoit

Reputation: 79243

It seems that the decoded message is an OCTET STRING encoded using Distinguished Encoding Rules as per https://en.wikipedia.org/wiki/X.690#DER_encoding. 04 is the tag number for OCTET STRING.

Upvotes: 2

Related Questions