| /* mz_crypt_win32.c -- Crypto/hash functions for Windows |
| Version 2.7.5, November 13, 2018 |
| part of the MiniZip project |
| |
| Copyright (C) 2010-2018 Nathan Moinvaziri |
| https://github.com/nmoinvaz/minizip |
| |
| This program is distributed under the terms of the same license as zlib. |
| See the accompanying LICENSE file for the full text of the license. |
| */ |
| |
| #pragma comment(lib, "crypt32.lib") |
| |
| #include <stdlib.h> |
| #include <stdint.h> |
| #include <string.h> |
| |
| #include <windows.h> |
| #include <wincrypt.h> |
| |
| #include "mz.h" |
| |
| #include "mz_os.h" |
| |
| /***************************************************************************/ |
| |
| int32_t mz_crypt_rand(uint8_t *buf, int32_t size) |
| { |
| HCRYPTPROV provider; |
| int32_t result = 0; |
| |
| |
| result = CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); |
| if (result) |
| { |
| result = CryptGenRandom(provider, size, buf); |
| CryptReleaseContext(provider, 0); |
| if (result) |
| return size; |
| } |
| |
| return mz_os_rand(buf, size); |
| } |
| |
| /***************************************************************************/ |
| |
| typedef struct mz_crypt_sha_s { |
| HCRYPTPROV provider; |
| HCRYPTHASH hash; |
| int32_t error; |
| uint16_t algorithm; |
| } mz_crypt_sha; |
| |
| /***************************************************************************/ |
| |
| void mz_crypt_sha_reset(void *handle) |
| { |
| mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
| if (sha->hash) |
| CryptDestroyHash(sha->hash); |
| sha->hash = 0; |
| if (sha->provider) |
| CryptReleaseContext(sha->provider, 0); |
| sha->provider = 0; |
| sha->error = 0; |
| } |
| |
| int32_t mz_crypt_sha_begin(void *handle) |
| { |
| mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
| ALG_ID alg_id = 0; |
| int32_t result = 0; |
| int32_t err = MZ_OK; |
| |
| |
| if (sha == NULL) |
| return MZ_PARAM_ERROR; |
| |
| if (sha->algorithm == MZ_HASH_SHA1) |
| alg_id = CALG_SHA1; |
| else |
| alg_id = CALG_SHA_256; |
| |
| result = CryptAcquireContext(&sha->provider, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); |
| if (!result) |
| { |
| sha->error = GetLastError(); |
| err = MZ_CRYPT_ERROR; |
| } |
| |
| if (result) |
| { |
| result = CryptCreateHash(sha->provider, alg_id, 0, 0, &sha->hash); |
| if (!result) |
| { |
| sha->error = GetLastError(); |
| err = MZ_HASH_ERROR; |
| } |
| } |
| |
| return err; |
| } |
| |
| int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size) |
| { |
| mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
| int32_t result = 0; |
| |
| if (sha == NULL || buf == NULL || sha->hash == 0) |
| return MZ_PARAM_ERROR; |
| result = CryptHashData(sha->hash, buf, size, 0); |
| if (!result) |
| { |
| sha->error = GetLastError(); |
| return MZ_HASH_ERROR; |
| } |
| return size; |
| } |
| |
| int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) |
| { |
| mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
| int32_t result = 0; |
| int32_t expected_size = 0; |
| |
| if (sha == NULL || digest == NULL || sha->hash == 0) |
| return MZ_PARAM_ERROR; |
| result = CryptGetHashParam(sha->hash, HP_HASHVAL, NULL, &expected_size, 0); |
| if (expected_size > digest_size) |
| return MZ_BUF_ERROR; |
| if (!result) |
| return MZ_HASH_ERROR; |
| result = CryptGetHashParam(sha->hash, HP_HASHVAL, digest, &digest_size, 0); |
| if (!result) |
| { |
| sha->error = GetLastError(); |
| return MZ_HASH_ERROR; |
| } |
| return MZ_OK; |
| } |
| |
| void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) |
| { |
| mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
| sha->algorithm = algorithm; |
| } |
| |
| void *mz_crypt_sha_create(void **handle) |
| { |
| mz_crypt_sha *sha = NULL; |
| |
| sha = (mz_crypt_sha *)MZ_ALLOC(sizeof(mz_crypt_sha)); |
| if (sha != NULL) |
| { |
| memset(sha, 0, sizeof(mz_crypt_sha)); |
| sha->algorithm = MZ_HASH_SHA256; |
| } |
| if (handle != NULL) |
| *handle = sha; |
| |
| return sha; |
| } |
| |
| void mz_crypt_sha_delete(void **handle) |
| { |
| mz_crypt_sha *sha = NULL; |
| if (handle == NULL) |
| return; |
| sha = (mz_crypt_sha *)*handle; |
| if (sha != NULL) |
| { |
| mz_crypt_sha_reset(*handle); |
| MZ_FREE(sha); |
| } |
| *handle = NULL; |
| } |
| |
| /***************************************************************************/ |
| |
| typedef struct mz_crypt_aes_s { |
| HCRYPTPROV provider; |
| HCRYPTKEY key; |
| int32_t mode; |
| int32_t error; |
| } mz_crypt_aes; |
| |
| /***************************************************************************/ |
| |
| static void mz_crypt_aes_free(void *handle) |
| { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| if (aes->key) |
| CryptDestroyKey(aes->key); |
| aes->key = 0; |
| if (aes->provider) |
| CryptReleaseContext(aes->provider, 0); |
| aes->provider = 0; |
| } |
| |
| void mz_crypt_aes_reset(void *handle) |
| { |
| mz_crypt_aes_free(handle); |
| } |
| |
| int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size) |
| { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| int32_t result = 0; |
| |
| if (aes == NULL || buf == NULL) |
| return MZ_PARAM_ERROR; |
| if (size != MZ_AES_BLOCK_SIZE) |
| return MZ_PARAM_ERROR; |
| result = CryptEncrypt(aes->key, 0, 0, 0, buf, &size, size); |
| if (!result) |
| { |
| aes->error = GetLastError(); |
| return MZ_CRYPT_ERROR; |
| } |
| return size; |
| } |
| |
| int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size) |
| { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| int32_t result = 0; |
| if (aes == NULL || buf == NULL) |
| return MZ_PARAM_ERROR; |
| if (size != MZ_AES_BLOCK_SIZE) |
| return MZ_PARAM_ERROR; |
| result = CryptDecrypt(aes->key, 0, 0, 0, buf, &size); |
| if (!result) |
| { |
| aes->error = GetLastError(); |
| return MZ_CRYPT_ERROR; |
| } |
| return size; |
| } |
| |
| static int32_t mz_crypt_aes_set_key(void *handle, const void *key, int32_t key_length) |
| { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| HCRYPTHASH hash = 0; |
| ALG_ID alg_id = 0; |
| typedef struct key_blob_header_s { |
| BLOBHEADER hdr; |
| uint32_t key_length; |
| } key_blob_header_s; |
| key_blob_header_s *key_blob_s = NULL; |
| uint8_t *key_blob = NULL; |
| int32_t key_blob_size = 0; |
| int32_t result = 0; |
| int32_t err = MZ_OK; |
| |
| |
| if (aes == NULL || key == NULL) |
| return MZ_PARAM_ERROR; |
| |
| mz_crypt_aes_reset(handle); |
| |
| if (key_length == MZ_AES_KEY_LENGTH(MZ_AES_ENCRYPTION_MODE_128)) |
| alg_id = CALG_AES_128; |
| else if (key_length == MZ_AES_KEY_LENGTH(MZ_AES_ENCRYPTION_MODE_192)) |
| alg_id = CALG_AES_192; |
| else if (key_length == MZ_AES_KEY_LENGTH(MZ_AES_ENCRYPTION_MODE_256)) |
| alg_id = CALG_AES_256; |
| else |
| return MZ_PARAM_ERROR; |
| |
| result = CryptAcquireContext(&aes->provider, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); |
| if (result) |
| { |
| key_blob_size = sizeof(key_blob_header_s) + key_length; |
| key_blob = (uint8_t *)MZ_ALLOC(key_blob_size); |
| |
| key_blob_s = (key_blob_header_s *)key_blob; |
| key_blob_s->hdr.bType = PLAINTEXTKEYBLOB; |
| key_blob_s->hdr.bVersion = CUR_BLOB_VERSION; |
| key_blob_s->hdr.aiKeyAlg = alg_id; |
| key_blob_s->hdr.reserved = 0; |
| key_blob_s->key_length = key_length; |
| |
| memcpy(key_blob + sizeof(key_blob_header_s), key, key_length); |
| |
| result = CryptImportKey(aes->provider, key_blob, key_blob_size, 0, CRYPT_IPSEC_HMAC_KEY, &aes->key); |
| } |
| if (!result) |
| { |
| aes->error = GetLastError(); |
| err = MZ_CRYPT_ERROR; |
| } |
| MZ_FREE(key_blob); |
| |
| if (hash) |
| CryptDestroyHash(hash); |
| |
| return err; |
| } |
| |
| int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length) |
| { |
| return mz_crypt_aes_set_key(handle, key, key_length); |
| } |
| |
| int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length) |
| { |
| return mz_crypt_aes_set_key(handle, key, key_length); |
| } |
| |
| void mz_crypt_aes_set_mode(void *handle, int32_t mode) |
| { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| aes->mode = mode; |
| } |
| |
| void *mz_crypt_aes_create(void **handle) |
| { |
| mz_crypt_aes *aes = NULL; |
| |
| aes = (mz_crypt_aes *)MZ_ALLOC(sizeof(mz_crypt_aes)); |
| if (aes != NULL) |
| memset(aes, 0, sizeof(mz_crypt_aes)); |
| if (handle != NULL) |
| *handle = aes; |
| |
| return aes; |
| } |
| |
| void mz_crypt_aes_delete(void **handle) |
| { |
| mz_crypt_aes *aes = NULL; |
| if (handle == NULL) |
| return; |
| aes = (mz_crypt_aes *)*handle; |
| if (aes != NULL) |
| { |
| mz_crypt_aes_free(*handle); |
| MZ_FREE(aes); |
| } |
| *handle = NULL; |
| } |
| |
| /***************************************************************************/ |
| |
| typedef struct mz_crypt_hmac_s { |
| HCRYPTPROV provider; |
| HCRYPTHASH hash; |
| HCRYPTKEY key; |
| HMAC_INFO info; |
| int32_t mode; |
| int32_t error; |
| uint16_t algorithm; |
| } mz_crypt_hmac; |
| |
| /***************************************************************************/ |
| |
| static void mz_crypt_hmac_free(void *handle) |
| { |
| mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
| if (hmac->key) |
| CryptDestroyKey(hmac->key); |
| hmac->key = 0; |
| if (hmac->hash) |
| CryptDestroyHash(hmac->hash); |
| hmac->hash = 0; |
| if (hmac->provider) |
| CryptReleaseContext(hmac->provider, 0); |
| hmac->provider = 0; |
| memset(&hmac->info, 0, sizeof(hmac->info)); |
| } |
| |
| void mz_crypt_hmac_reset(void *handle) |
| { |
| mz_crypt_hmac_free(handle); |
| } |
| |
| int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) |
| { |
| mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
| ALG_ID alg_id = 0; |
| typedef struct key_blob_header_s { |
| BLOBHEADER hdr; |
| uint32_t key_length; |
| } key_blob_header_s; |
| key_blob_header_s *key_blob_s = NULL; |
| uint8_t *key_blob = NULL; |
| int32_t key_blob_size = 0; |
| int32_t result = 0; |
| int32_t err = MZ_OK; |
| |
| |
| if (hmac == NULL || key == NULL) |
| return MZ_PARAM_ERROR; |
| |
| mz_crypt_hmac_reset(handle); |
| |
| if (hmac->algorithm == MZ_HASH_SHA1) |
| alg_id = CALG_SHA1; |
| else |
| alg_id = CALG_SHA_256; |
| |
| hmac->info.HashAlgid = alg_id; |
| |
| result = CryptAcquireContext(&hmac->provider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, |
| CRYPT_VERIFYCONTEXT | CRYPT_SILENT); |
| |
| if (!result) |
| { |
| hmac->error = GetLastError(); |
| err = MZ_CRYPT_ERROR; |
| } |
| |
| key_blob_size = sizeof(key_blob_header_s) + key_length; |
| key_blob = (uint8_t *)MZ_ALLOC(key_blob_size); |
| |
| key_blob_s = (key_blob_header_s *)key_blob; |
| key_blob_s->hdr.bType = PLAINTEXTKEYBLOB; |
| key_blob_s->hdr.bVersion = CUR_BLOB_VERSION; |
| key_blob_s->hdr.aiKeyAlg = CALG_RC2; |
| key_blob_s->hdr.reserved = 0; |
| key_blob_s->key_length = key_length; |
| |
| memcpy(key_blob + sizeof(key_blob_header_s), key, key_length); |
| |
| result = CryptImportKey(hmac->provider, key_blob, key_blob_size, 0, CRYPT_IPSEC_HMAC_KEY, &hmac->key); |
| if (result) |
| result = CryptCreateHash(hmac->provider, CALG_HMAC, hmac->key, 0, &hmac->hash); |
| if (result) |
| result = CryptSetHashParam(hmac->hash, HP_HMAC_INFO, (uint8_t *)&hmac->info, 0); |
| if (!result) |
| { |
| hmac->error = GetLastError(); |
| err = MZ_CRYPT_ERROR; |
| } |
| |
| MZ_FREE(key_blob); |
| |
| if (err != MZ_OK) |
| mz_crypt_hmac_free(handle); |
| |
| return err; |
| } |
| |
| int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size) |
| { |
| mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
| int32_t result = 0; |
| |
| if (hmac == NULL || buf == NULL || hmac->hash == 0) |
| return MZ_PARAM_ERROR; |
| |
| result = CryptHashData(hmac->hash, buf, size, 0); |
| if (!result) |
| { |
| hmac->error = GetLastError(); |
| return MZ_HASH_ERROR; |
| } |
| return MZ_OK; |
| } |
| |
| int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size) |
| { |
| mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
| int32_t result = 0; |
| int32_t expected_size = 0; |
| |
| if (hmac == NULL || digest == NULL || hmac->hash == 0) |
| return MZ_PARAM_ERROR; |
| result = CryptGetHashParam(hmac->hash, HP_HASHVAL, NULL, &expected_size, 0); |
| if (expected_size > digest_size) |
| return MZ_BUF_ERROR; |
| if (!result) |
| return MZ_HASH_ERROR; |
| result = CryptGetHashParam(hmac->hash, HP_HASHVAL, digest, &digest_size, 0); |
| if (!result) |
| { |
| hmac->error = GetLastError(); |
| return MZ_HASH_ERROR; |
| } |
| return MZ_OK; |
| } |
| |
| void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm) |
| { |
| mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
| hmac->algorithm = algorithm; |
| } |
| |
| int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) |
| { |
| mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle; |
| mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle; |
| int32_t result = 0; |
| int32_t err = MZ_OK; |
| |
| result = CryptDuplicateHash(source->hash, NULL, 0, &target->hash); |
| |
| if (!result) |
| { |
| target->error = GetLastError(); |
| err = MZ_HASH_ERROR; |
| } |
| return MZ_OK; |
| } |
| |
| void *mz_crypt_hmac_create(void **handle) |
| { |
| mz_crypt_hmac *hmac = NULL; |
| |
| hmac = (mz_crypt_hmac *)MZ_ALLOC(sizeof(mz_crypt_hmac)); |
| if (hmac != NULL) |
| { |
| memset(hmac, 0, sizeof(mz_crypt_hmac)); |
| hmac->algorithm = MZ_HASH_SHA256; |
| } |
| if (handle != NULL) |
| *handle = hmac; |
| |
| return hmac; |
| } |
| |
| void mz_crypt_hmac_delete(void **handle) |
| { |
| mz_crypt_hmac *hmac = NULL; |
| if (handle == NULL) |
| return; |
| hmac = (mz_crypt_hmac *)*handle; |
| if (hmac != NULL) |
| { |
| mz_crypt_hmac_free(*handle); |
| MZ_FREE(hmac); |
| } |
| *handle = NULL; |
| } |
| |
| /***************************************************************************/ |
| |
| int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size, |
| const char *cert_pwd, uint8_t **signature, int32_t *signature_size) |
| { |
| CRYPT_SIGN_MESSAGE_PARA sign_params; |
| CRYPT_DATA_BLOB cert_data_blob; |
| PCCERT_CONTEXT cert_context = NULL; |
| HCERTSTORE cert_store = 0; |
| wchar_t *password_wide = NULL; |
| int32_t result = 0; |
| int32_t err = MZ_OK; |
| uint32_t messages_sizes[1]; |
| uint8_t *messages[1]; |
| |
| |
| if (message == NULL || cert_data == NULL || signature == NULL || signature_size == NULL) |
| return MZ_PARAM_ERROR; |
| |
| *signature = NULL; |
| *signature_size = 0; |
| |
| cert_data_blob.pbData = cert_data; |
| cert_data_blob.cbData = cert_data_size; |
| |
| password_wide = mz_os_unicode_string_create(cert_pwd, MZ_ENCODING_UTF8); |
| if (password_wide) |
| { |
| cert_store = PFXImportCertStore(&cert_data_blob, password_wide, 0); |
| mz_os_unicode_string_delete(&password_wide); |
| } |
| |
| if (cert_store == NULL) |
| cert_store = PFXImportCertStore(&cert_data_blob, L"", 0); |
| if (cert_store == NULL) |
| cert_store = PFXImportCertStore(&cert_data_blob, NULL, 0); |
| if (cert_store == NULL) |
| return MZ_PARAM_ERROR; |
| |
| if (err == MZ_OK) |
| { |
| cert_context = CertFindCertificateInStore(cert_store, |
| X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_HAS_PRIVATE_KEY, NULL, NULL); |
| if (cert_context == NULL) |
| err = MZ_PARAM_ERROR; |
| } |
| if (err == MZ_OK) |
| { |
| memset(&sign_params, 0, sizeof(sign_params)); |
| |
| sign_params.cbSize = sizeof(sign_params); |
| sign_params.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING; |
| sign_params.pSigningCert = cert_context; |
| sign_params.HashAlgorithm.pszObjId = szOID_NIST_sha256; |
| sign_params.cMsgCert = 1; |
| sign_params.rgpMsgCert = &cert_context; |
| |
| messages[0] = message; |
| messages_sizes[0] = message_size; |
| |
| #if 0 // Timestamp support |
| CRYPT_ATTR_BLOB crypt_blob; |
| CRYPT_TIMESTAMP_CONTEXT *ts_context = NULL; |
| CRYPT_ATTRIBUTE unauth_attribs[1]; |
| wchar_t *timestamp_url_wide = NULL; |
| const char *timestamp_url = NULL; |
| |
| if (timestamp_url != NULL) |
| timestamp_url_wide = mz_os_unicode_string_create(timestamp_url); |
| if (timestamp_url_wide != NULL) |
| { |
| result = CryptRetrieveTimeStamp(timestamp_url_wide, |
| TIMESTAMP_NO_AUTH_RETRIEVAL | TIMESTAMP_VERIFY_CONTEXT_SIGNATURE, 0, szOID_NIST_sha256, |
| NULL, message, message_size, &ts_context, NULL, NULL); |
| |
| mz_os_unicode_string_delete(×tamp_url_wide); |
| |
| if ((result) && (ts_context != NULL)) |
| { |
| crypt_blob.cbData = ts_context->cbEncoded; |
| crypt_blob.pbData = ts_context->pbEncoded; |
| |
| unauth_attribs[0].pszObjId = "1.2.840.113549.1.9.16.2.14"; //id-smime-aa-timeStampToken |
| unauth_attribs[0].cValue = 1; |
| unauth_attribs[0].rgValue = &crypt_blob; |
| |
| sign_params.rgUnauthAttr = &unauth_attribs[0]; |
| sign_params.cUnauthAttr = 1; |
| } |
| } |
| |
| if (ts_context != NULL) |
| CryptMemFree(ts_context); |
| |
| if (result) |
| #endif |
| |
| result = CryptSignMessage(&sign_params, FALSE, 1, messages, messages_sizes, |
| NULL, signature_size); |
| |
| if (result && *signature_size > 0) |
| *signature = (uint8_t *)MZ_ALLOC(*signature_size); |
| |
| if (result && *signature != NULL) |
| result = CryptSignMessage(&sign_params, FALSE, 1, messages, messages_sizes, |
| *signature, signature_size); |
| |
| if (!result) |
| err = MZ_SIGN_ERROR; |
| } |
| |
| if (cert_context != NULL) |
| CertFreeCertificateContext(cert_context); |
| if (cert_store != NULL) |
| CertCloseStore(cert_store, 0); |
| |
| return err; |
| } |
| |
| int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size) |
| { |
| CRYPT_VERIFY_MESSAGE_PARA verify_params; |
| HCRYPTMSG crypt_msg = 0; |
| int32_t result = 0; |
| int32_t err = MZ_SIGN_ERROR; |
| uint8_t *decoded = NULL; |
| int32_t decoded_size = 0; |
| |
| |
| memset(&verify_params, 0, sizeof(verify_params)); |
| |
| verify_params.cbSize = sizeof(verify_params); |
| |
| verify_params.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING; |
| verify_params.hCryptProv = 0; |
| verify_params.pfnGetSignerCertificate = NULL; |
| verify_params.pvGetArg = NULL; |
| |
| result = CryptVerifyMessageSignature(&verify_params, 0, signature, signature_size, |
| NULL, &decoded_size, NULL); |
| |
| if (result && decoded_size > 0) |
| decoded = (uint8_t *)MZ_ALLOC(decoded_size); |
| |
| if (result) |
| result = CryptVerifyMessageSignature(&verify_params, 0, signature, signature_size, |
| decoded, &decoded_size, NULL); |
| |
| crypt_msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, 0, NULL, NULL); |
| if (crypt_msg != NULL) |
| { |
| #if 0 // Timestamp support |
| PCRYPT_ATTRIBUTES unauth_attribs = NULL; |
| HCRYPTMSG ts_msg = 0; |
| uint8_t *ts_content = NULL; |
| int32_t ts_content_size = 0; |
| uint8_t *ts_signature = NULL; |
| int32_t ts_signature_size = 0; |
| |
| result = CryptMsgUpdate(crypt_msg, signature, signature_size, 1); |
| |
| if (result) |
| CryptMsgGetParam(crypt_msg, CMSG_SIGNER_UNAUTH_ATTR_PARAM, 0, NULL, &ts_signature_size); |
| |
| if ((result) && (ts_signature_size > 0)) |
| ts_signature = (uint8_t *)MZ_ALLOC(ts_signature_size); |
| |
| if ((result) && (ts_signature != NULL)) |
| { |
| result = CryptMsgGetParam(crypt_msg, CMSG_SIGNER_UNAUTH_ATTR_PARAM, 0, ts_signature, |
| &ts_signature_size); |
| if (result) |
| { |
| unauth_attribs = (PCRYPT_ATTRIBUTES)ts_signature; |
| |
| if ((unauth_attribs->cAttr > 0) && (unauth_attribs->rgAttr[0].cValue > 0)) |
| { |
| ts_content = unauth_attribs->rgAttr[0].rgValue->pbData; |
| ts_content_size = unauth_attribs->rgAttr[0].rgValue->cbData; |
| } |
| } |
| |
| if ((result) && (ts_content != NULL)) |
| result = CryptVerifyTimeStampSignature(ts_content, ts_content_size, decoded, |
| decoded_size, 0, &crypt_context, NULL, NULL); |
| |
| if (result) |
| err = MZ_OK; |
| } |
| |
| if (ts_signature != NULL) |
| MZ_FREE(ts_signature); |
| |
| if (crypt_context != NULL) |
| CryptMemFree(crypt_context); |
| #endif |
| } |
| |
| if ((crypt_msg != NULL) && (result) && (decoded_size == message_size)) |
| { |
| // Verify cms message with our stored message |
| if (memcmp(decoded, message, message_size) == 0) |
| err = MZ_OK; |
| } |
| |
| if (crypt_msg != NULL) |
| CryptMsgClose(crypt_msg); |
| |
| if (decoded != NULL) |
| MZ_FREE(decoded); |
| |
| return err; |
| } |