| /* mz_crypt_openssl.c -- Crypto/hash functions for OpenSSL |
| part of the minizip-ng project |
| |
| Copyright (C) Nathan Moinvaziri |
| https://github.com/zlib-ng/minizip-ng |
| |
| 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. |
| */ |
| |
| #include "mz.h" |
| #include "mz_crypt.h" |
| |
| #include <openssl/err.h> |
| #include <openssl/engine.h> |
| #include <openssl/rand.h> |
| #include <openssl/sha.h> |
| #include <openssl/aes.h> |
| #include <openssl/crypto.h> |
| #include <openssl/evp.h> |
| #include <openssl/hmac.h> |
| |
| #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
| # include <openssl/core_names.h> |
| #endif |
| |
| /***************************************************************************/ |
| |
| static void mz_crypt_init(void) { |
| static int32_t openssl_initialized = 0; |
| if (!openssl_initialized) { |
| #if OPENSSL_VERSION_NUMBER < 0x10100000L |
| OpenSSL_add_all_algorithms(); |
| |
| ERR_load_BIO_strings(); |
| ERR_load_crypto_strings(); |
| |
| ENGINE_load_builtin_engines(); |
| ENGINE_register_all_complete(); |
| #else |
| OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL); |
| #endif |
| |
| openssl_initialized = 1; |
| } |
| } |
| |
| int32_t mz_crypt_rand(uint8_t *buf, int32_t size) { |
| if (!RAND_bytes(buf, size)) |
| return MZ_CRYPT_ERROR; |
| |
| return size; |
| } |
| |
| /***************************************************************************/ |
| |
| typedef struct mz_crypt_sha_s { |
| #if OPENSSL_VERSION_NUMBER < 0x10100000L |
| union { |
| SHA512_CTX ctx512; |
| SHA256_CTX ctx256; |
| SHA_CTX ctx1; |
| }; |
| #else |
| EVP_MD_CTX *ctx; |
| #endif |
| int32_t initialized; |
| int32_t error; |
| uint16_t algorithm; |
| } mz_crypt_sha; |
| |
| /***************************************************************************/ |
| |
| static const uint8_t mz_crypt_sha_digest_size[] = { |
| MZ_HASH_SHA1_SIZE, 0, MZ_HASH_SHA224_SIZE, |
| MZ_HASH_SHA256_SIZE, MZ_HASH_SHA384_SIZE, MZ_HASH_SHA512_SIZE |
| }; |
| |
| /***************************************************************************/ |
| |
| static void mz_crypt_sha_free(void *handle) { |
| #if OPENSSL_VERSION_NUMBER >= 0x10100000L |
| mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
| if (sha->ctx) |
| EVP_MD_CTX_free(sha->ctx); |
| sha->ctx = NULL; |
| #else |
| MZ_UNUSED(handle); |
| #endif |
| } |
| |
| void mz_crypt_sha_reset(void *handle) { |
| mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
| |
| mz_crypt_init(); |
| mz_crypt_sha_free(handle); |
| |
| sha->error = 0; |
| sha->initialized = 0; |
| } |
| |
| int32_t mz_crypt_sha_begin(void *handle) { |
| mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
| int32_t result = 0; |
| |
| if (!sha) |
| return MZ_PARAM_ERROR; |
| |
| mz_crypt_sha_reset(handle); |
| |
| #if OPENSSL_VERSION_NUMBER < 0x10100000L |
| switch (sha->algorithm) { |
| case MZ_HASH_SHA1: |
| result = SHA1_Init(&sha->ctx1); |
| break; |
| case MZ_HASH_SHA224: |
| result = SHA224_Init(&sha->ctx256); |
| break; |
| case MZ_HASH_SHA256: |
| result = SHA256_Init(&sha->ctx256); |
| break; |
| case MZ_HASH_SHA384: |
| result = SHA384_Init(&sha->ctx512); |
| break; |
| case MZ_HASH_SHA512: |
| result = SHA512_Init(&sha->ctx512); |
| break; |
| } |
| #else |
| const EVP_MD *md = NULL; |
| switch (sha->algorithm) { |
| case MZ_HASH_SHA1: |
| md = EVP_sha1(); |
| break; |
| case MZ_HASH_SHA224: |
| md = EVP_sha224(); |
| break; |
| case MZ_HASH_SHA256: |
| md = EVP_sha256(); |
| break; |
| case MZ_HASH_SHA384: |
| md = EVP_sha384(); |
| break; |
| case MZ_HASH_SHA512: |
| md = EVP_sha512(); |
| break; |
| } |
| if (!md) |
| return MZ_PARAM_ERROR; |
| |
| sha->ctx = EVP_MD_CTX_new(); |
| if (!sha->ctx) |
| return MZ_MEM_ERROR; |
| result = EVP_DigestInit_ex(sha->ctx, md, NULL); |
| #endif |
| |
| if (!result) { |
| sha->error = ERR_get_error(); |
| return MZ_HASH_ERROR; |
| } |
| |
| sha->initialized = 1; |
| return MZ_OK; |
| } |
| |
| 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 || !buf || !sha->initialized) |
| return MZ_PARAM_ERROR; |
| |
| #if OPENSSL_VERSION_NUMBER < 0x10100000L |
| switch (sha->algorithm) { |
| case MZ_HASH_SHA1: |
| result = SHA1_Update(&sha->ctx1, buf, size); |
| break; |
| case MZ_HASH_SHA224: |
| result = SHA224_Update(&sha->ctx256, buf, size); |
| break; |
| case MZ_HASH_SHA256: |
| result = SHA256_Update(&sha->ctx256, buf, size); |
| break; |
| case MZ_HASH_SHA384: |
| result = SHA384_Update(&sha->ctx512, buf, size); |
| break; |
| case MZ_HASH_SHA512: |
| result = SHA512_Update(&sha->ctx512, buf, size); |
| break; |
| } |
| #else |
| result = EVP_DigestUpdate(sha->ctx, buf, size); |
| #endif |
| |
| if (!result) { |
| sha->error = ERR_get_error(); |
| 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; |
| |
| if (!sha || !digest || !sha->initialized) |
| return MZ_PARAM_ERROR; |
| if (digest_size < mz_crypt_sha_digest_size[sha->algorithm - MZ_HASH_SHA1]) |
| return MZ_PARAM_ERROR; |
| |
| #if OPENSSL_VERSION_NUMBER < 0x10100000L |
| switch (sha->algorithm) { |
| case MZ_HASH_SHA1: |
| result = SHA1_Final(digest, &sha->ctx1); |
| break; |
| case MZ_HASH_SHA224: |
| result = SHA224_Final(digest, &sha->ctx256); |
| break; |
| case MZ_HASH_SHA256: |
| result = SHA256_Final(digest, &sha->ctx256); |
| break; |
| case MZ_HASH_SHA384: |
| result = SHA384_Final(digest, &sha->ctx512); |
| break; |
| case MZ_HASH_SHA512: |
| result = SHA512_Final(digest, &sha->ctx512); |
| break; |
| } |
| #else |
| result = EVP_DigestFinal_ex(sha->ctx, digest, NULL); |
| #endif |
| |
| if (!result) { |
| sha->error = ERR_get_error(); |
| return MZ_HASH_ERROR; |
| } |
| |
| return MZ_OK; |
| } |
| |
| int32_t mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) { |
| mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
| if (algorithm < MZ_HASH_SHA1 || algorithm > MZ_HASH_SHA512) |
| return MZ_PARAM_ERROR; |
| sha->algorithm = algorithm; |
| return MZ_OK; |
| } |
| |
| void *mz_crypt_sha_create(void) { |
| mz_crypt_sha *sha = (mz_crypt_sha *)calloc(1, sizeof(mz_crypt_sha)); |
| if (sha) |
| sha->algorithm = MZ_HASH_SHA256; |
| return sha; |
| } |
| |
| void mz_crypt_sha_delete(void **handle) { |
| mz_crypt_sha *sha = NULL; |
| if (!handle) |
| return; |
| sha = (mz_crypt_sha *)*handle; |
| if (sha) { |
| mz_crypt_sha_free(*handle); |
| free(sha); |
| } |
| *handle = NULL; |
| } |
| |
| /***************************************************************************/ |
| |
| typedef struct mz_crypt_aes_s { |
| int32_t mode; |
| int32_t error; |
| EVP_CIPHER_CTX *ctx; |
| } mz_crypt_aes; |
| |
| /***************************************************************************/ |
| |
| static void mz_crypt_aes_free(void *handle) { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| if (aes->ctx) |
| EVP_CIPHER_CTX_free(aes->ctx); |
| aes->ctx = NULL; |
| } |
| |
| void mz_crypt_aes_reset(void *handle) { |
| mz_crypt_init(); |
| mz_crypt_aes_free(handle); |
| } |
| |
| int32_t mz_crypt_aes_encrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| |
| if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || !aes->ctx) |
| return MZ_PARAM_ERROR; |
| if (aes->mode != MZ_AES_MODE_GCM && aad && aad_size > 0) |
| return MZ_PARAM_ERROR; |
| |
| if (aad && aad_size > 0) { |
| int32_t how_many = 0; |
| if (!EVP_EncryptUpdate(aes->ctx, NULL, &how_many, aad, aad_size)) |
| return MZ_CRYPT_ERROR; |
| } |
| |
| if (!EVP_EncryptUpdate(aes->ctx, buf, &size, buf, size)) |
| return MZ_CRYPT_ERROR; |
| |
| return size; |
| } |
| |
| int32_t mz_crypt_aes_encrypt_final(void *handle, uint8_t *buf, int32_t size, uint8_t *tag, int32_t tag_size) { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| int result = 0; |
| int out_len = 0; |
| |
| if (!aes || !tag || !tag_size || !aes->ctx || aes->mode != MZ_AES_MODE_GCM) |
| return MZ_PARAM_ERROR; |
| |
| if (buf && size) { |
| if (!EVP_EncryptUpdate(aes->ctx, buf, &size, buf, size)) |
| return MZ_CRYPT_ERROR; |
| } |
| |
| /* Must call EncryptFinal for tag to be calculated */ |
| result = EVP_EncryptFinal_ex(aes->ctx, NULL, &out_len); |
| |
| if (result) |
| result = EVP_CIPHER_CTX_ctrl(aes->ctx, EVP_CTRL_GCM_GET_TAG, tag_size, tag); |
| |
| if (!result) { |
| aes->error = ERR_get_error(); |
| return MZ_CRYPT_ERROR; |
| } |
| |
| return size; |
| } |
| |
| int32_t mz_crypt_aes_decrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| |
| if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || !aes->ctx) |
| return MZ_PARAM_ERROR; |
| if (aes->mode != MZ_AES_MODE_GCM && aad && aad_size > 0) |
| return MZ_PARAM_ERROR; |
| |
| if (aad && aad_size > 0) { |
| int32_t how_many = 0; |
| if (!EVP_DecryptUpdate(aes->ctx, NULL, &how_many, aad, aad_size)) |
| return MZ_CRYPT_ERROR; |
| } |
| |
| if (!EVP_DecryptUpdate(aes->ctx, buf, &size, buf, size)) |
| return MZ_CRYPT_ERROR; |
| |
| return size; |
| } |
| |
| int32_t mz_crypt_aes_decrypt_final(void *handle, uint8_t *buf, int32_t size, const uint8_t *tag, int32_t tag_length) { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| int out_len = 0; |
| |
| if (!aes || !tag || !tag_length || !aes->ctx || aes->mode != MZ_AES_MODE_GCM) |
| return MZ_PARAM_ERROR; |
| |
| if (buf && size) { |
| if (!EVP_DecryptUpdate(aes->ctx, buf, &size, buf, size)) |
| return MZ_CRYPT_ERROR; |
| } |
| |
| /* Set expected tag */ |
| if (!EVP_CIPHER_CTX_ctrl(aes->ctx, EVP_CTRL_GCM_SET_TAG, tag_length, (void *)tag)) { |
| aes->error = ERR_get_error(); |
| return MZ_CRYPT_ERROR; |
| } |
| |
| /* Must call DecryptFinal for tag verification */ |
| if (!EVP_DecryptFinal_ex(aes->ctx, NULL, &out_len)) { |
| aes->error = ERR_get_error(); |
| return MZ_CRYPT_ERROR; |
| } |
| |
| return size; |
| } |
| |
| static int32_t mz_crypt_aes_set_key(void *handle, const void *key, int32_t key_length, |
| const void *iv, int32_t iv_length, int32_t encrypt) { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| const EVP_CIPHER *type = NULL; |
| |
| switch (aes->mode) { |
| case MZ_AES_MODE_CBC: |
| if (key_length == 16) |
| type = EVP_aes_128_cbc(); |
| else if (key_length == 24) |
| type = EVP_aes_192_cbc(); |
| else if (key_length == 32) |
| type = EVP_aes_256_cbc(); |
| break; |
| case MZ_AES_MODE_ECB: |
| if (key_length == 16) |
| type = EVP_aes_128_ecb(); |
| else if (key_length == 24) |
| type = EVP_aes_192_ecb(); |
| else if (key_length == 32) |
| type = EVP_aes_256_ecb(); |
| break; |
| case MZ_AES_MODE_GCM: |
| if (key_length == 16) |
| type = EVP_aes_128_gcm(); |
| else if (key_length == 24) |
| type = EVP_aes_192_gcm(); |
| else if (key_length == 32) |
| type = EVP_aes_256_gcm(); |
| break; |
| } |
| if (!type) |
| return MZ_PARAM_ERROR; |
| |
| aes->ctx = EVP_CIPHER_CTX_new(); |
| if (!aes->ctx) |
| return MZ_MEM_ERROR; |
| |
| if (!EVP_CipherInit_ex(aes->ctx, type, NULL, key, iv, encrypt)) { |
| aes->error = ERR_get_error(); |
| return MZ_HASH_ERROR; |
| } |
| |
| EVP_CIPHER_CTX_set_padding(aes->ctx, aes->mode == MZ_AES_MODE_GCM); |
| |
| return MZ_OK; |
| } |
| |
| int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length, |
| const void *iv, int32_t iv_length) { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| |
| if (!aes || !key || !key_length) |
| return MZ_PARAM_ERROR; |
| if (key_length != 16 && key_length != 24 && key_length != 32) |
| return MZ_PARAM_ERROR; |
| if (iv && iv_length != MZ_AES_BLOCK_SIZE) |
| return MZ_PARAM_ERROR; |
| |
| mz_crypt_aes_reset(handle); |
| |
| return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length, 1); |
| } |
| |
| int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length, |
| const void *iv, int32_t iv_length) { |
| mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
| |
| if (!aes || !key || !key_length) |
| return MZ_PARAM_ERROR; |
| if (key_length != 16 && key_length != 24 && key_length != 32) |
| return MZ_PARAM_ERROR; |
| if (iv && iv_length > MZ_AES_BLOCK_SIZE) |
| return MZ_PARAM_ERROR; |
| |
| mz_crypt_aes_reset(handle); |
| |
| return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length, 0); |
| } |
| |
| 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) { |
| mz_crypt_aes *aes = (mz_crypt_aes *)calloc(1, sizeof(mz_crypt_aes)); |
| return aes; |
| } |
| |
| void mz_crypt_aes_delete(void **handle) { |
| mz_crypt_aes *aes = NULL; |
| if (!handle) |
| return; |
| aes = (mz_crypt_aes *)*handle; |
| if (aes) { |
| mz_crypt_aes_free(*handle); |
| free(aes); |
| } |
| *handle = NULL; |
| } |
| |
| /***************************************************************************/ |
| |
| typedef struct mz_crypt_hmac_s { |
| #if OPENSSL_VERSION_NUMBER < 0x30000000L |
| HMAC_CTX *ctx; |
| #else |
| EVP_MAC *mac; |
| EVP_MAC_CTX *ctx; |
| #endif |
| int32_t initialized; |
| int32_t error; |
| uint16_t algorithm; |
| } mz_crypt_hmac; |
| |
| /***************************************************************************/ |
| |
| #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \ |
| (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2070000fL)) |
| static HMAC_CTX *HMAC_CTX_new(void) { |
| HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX)); |
| if (ctx) |
| HMAC_CTX_init(ctx); |
| return ctx; |
| } |
| |
| static void HMAC_CTX_free(HMAC_CTX *ctx) { |
| if (ctx) { |
| HMAC_CTX_cleanup(ctx); |
| OPENSSL_free(ctx); |
| } |
| } |
| #endif |
| |
| /***************************************************************************/ |
| |
| static void mz_crypt_hmac_free(void *handle) { |
| mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
| |
| #if OPENSSL_VERSION_NUMBER < 0x30000000L |
| HMAC_CTX_free(hmac->ctx); |
| #else |
| if (hmac->ctx) |
| EVP_MAC_CTX_free(hmac->ctx); |
| if (hmac->mac) |
| EVP_MAC_free(hmac->mac); |
| hmac->mac = NULL; |
| #endif |
| |
| hmac->ctx = NULL; |
| } |
| |
| void mz_crypt_hmac_reset(void *handle) { |
| mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
| |
| mz_crypt_init(); |
| mz_crypt_hmac_free(handle); |
| |
| hmac->error = 0; |
| } |
| |
| int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) { |
| mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
| int32_t result = 0; |
| |
| if (!hmac || !key) |
| return MZ_PARAM_ERROR; |
| |
| mz_crypt_hmac_reset(handle); |
| |
| #if OPENSSL_VERSION_NUMBER < 0x30000000L |
| const EVP_MD *evp_md = NULL; |
| |
| if (hmac->algorithm == MZ_HASH_SHA1) |
| evp_md = EVP_sha1(); |
| else |
| evp_md = EVP_sha256(); |
| |
| hmac->ctx = HMAC_CTX_new(); |
| if (!hmac->ctx) |
| return MZ_MEM_ERROR; |
| |
| result = HMAC_Init_ex(hmac->ctx, key, key_length, evp_md, NULL); |
| #else |
| char *digest_algorithm = NULL; |
| OSSL_PARAM params[2]; |
| |
| if (hmac->algorithm == MZ_HASH_SHA1) |
| digest_algorithm = "sha1"; |
| else |
| digest_algorithm = "sha256"; |
| |
| params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, digest_algorithm, 0); |
| params[1] = OSSL_PARAM_construct_end(); |
| |
| hmac->mac = EVP_MAC_fetch(NULL, "HMAC", NULL); |
| if (!hmac->mac) |
| return MZ_MEM_ERROR; |
| hmac->ctx = EVP_MAC_CTX_new(hmac->mac); |
| if (!hmac->ctx) |
| return MZ_MEM_ERROR; |
| result = EVP_MAC_init(hmac->ctx, key, key_length, params); |
| #endif |
| |
| if (!result) { |
| hmac->error = ERR_get_error(); |
| return MZ_HASH_ERROR; |
| } |
| |
| return MZ_OK; |
| } |
| |
| 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 || !buf) |
| return MZ_PARAM_ERROR; |
| |
| #if OPENSSL_VERSION_NUMBER < 0x30000000L |
| result = HMAC_Update(hmac->ctx, buf, size); |
| #else |
| result = EVP_MAC_update(hmac->ctx, buf, size); |
| #endif |
| if (!result) { |
| hmac->error = ERR_get_error(); |
| 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; |
| |
| if (!hmac || !digest) |
| return MZ_PARAM_ERROR; |
| |
| #if OPENSSL_VERSION_NUMBER < 0x30000000L |
| if (hmac->algorithm == MZ_HASH_SHA1) { |
| if (digest_size < MZ_HASH_SHA1_SIZE) |
| return MZ_BUF_ERROR; |
| |
| result = HMAC_Final(hmac->ctx, digest, (uint32_t *)&digest_size); |
| } else { |
| if (digest_size < MZ_HASH_SHA256_SIZE) |
| return MZ_BUF_ERROR; |
| result = HMAC_Final(hmac->ctx, digest, (uint32_t *)&digest_size); |
| } |
| #else |
| { |
| size_t digest_outsize = digest_size; |
| result = EVP_MAC_final(hmac->ctx, digest, &digest_outsize, digest_size); |
| } |
| #endif |
| |
| if (!result) { |
| hmac->error = ERR_get_error(); |
| 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; |
| |
| if (!source || !target) |
| return MZ_PARAM_ERROR; |
| |
| mz_crypt_hmac_reset(target_handle); |
| |
| #if OPENSSL_VERSION_NUMBER < 0x30000000L |
| if (!target->ctx) |
| target->ctx = HMAC_CTX_new(); |
| |
| if (!HMAC_CTX_copy(target->ctx, source->ctx)) { |
| target->error = ERR_get_error(); |
| return MZ_HASH_ERROR; |
| } |
| #else |
| if (!target->ctx) |
| target->ctx = EVP_MAC_CTX_dup(source->ctx); |
| if (!target->ctx) |
| return MZ_MEM_ERROR; |
| #endif |
| |
| return MZ_OK; |
| } |
| |
| void *mz_crypt_hmac_create(void) { |
| mz_crypt_hmac *hmac = (mz_crypt_hmac *)calloc(1, sizeof(mz_crypt_hmac)); |
| if (hmac) |
| hmac->algorithm = MZ_HASH_SHA256; |
| return hmac; |
| } |
| |
| void mz_crypt_hmac_delete(void **handle) { |
| mz_crypt_hmac *hmac = NULL; |
| if (!handle) |
| return; |
| hmac = (mz_crypt_hmac *)*handle; |
| if (hmac) { |
| mz_crypt_hmac_free(*handle); |
| free(hmac); |
| } |
| *handle = NULL; |
| } |