static int SSKDF_hash_kdm(const EVP_MD *kdf_md,
                          const unsigned char *z, size_t z_len,
                          const unsigned char *info, size_t info_len,
                          unsigned char *derived_key, size_t derived_key_len)
{
    int ret = 0, hlen;
    size_t counter, out_len, len = derived_key_len;
    unsigned char c[4];
    unsigned char mac[EVP_MAX_MD_SIZE];
    unsigned char *out = derived_key;
    EVP_MD_CTX *ctx = NULL, *ctx_init = NULL;
    if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
            || derived_key_len > SSKDF_MAX_INLEN
            || derived_key_len == 0)
        return 0;
    hlen = EVP_MD_size(kdf_md);
    if (hlen <= 0)
        return 0;
    out_len = (size_t)hlen;
    ctx = EVP_MD_CTX_create();
    ctx_init = EVP_MD_CTX_create();
    if (ctx == NULL || ctx_init == NULL)
        goto end;
    if (!EVP_DigestInit(ctx_init, kdf_md))
        goto end;
    for (counter = 1;; counter++) {
        c[0] = (unsigned char)((counter >> 24) & 0xff);
        c[1] = (unsigned char)((counter >> 16) & 0xff);
        c[2] = (unsigned char)((counter >> 8) & 0xff);
        c[3] = (unsigned char)(counter & 0xff);
        if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init)
                && EVP_DigestUpdate(ctx, c, sizeof(c))
                && EVP_DigestUpdate(ctx, z, z_len)
                && EVP_DigestUpdate(ctx, info, info_len)))
            goto end;
        if (len >= out_len) {
            if (!EVP_DigestFinal_ex(ctx, out, NULL))
                goto end;
            out += out_len;
            len -= out_len;
            if (len == 0)
                break;
        } else {
            if (!EVP_DigestFinal_ex(ctx, mac, NULL))
                goto end;
            memcpy(out, mac, len);
            break;
        }
    }
    ret = 1;
end:
    EVP_MD_CTX_destroy(ctx);
    EVP_MD_CTX_destroy(ctx_init);
    OPENSSL_cleanse(mac, sizeof(mac));
    return ret;
}
['static int SSKDF_hash_kdm(const EVP_MD *kdf_md,\n                          const unsigned char *z, size_t z_len,\n                          const unsigned char *info, size_t info_len,\n                          unsigned char *derived_key, size_t derived_key_len)\n{\n    int ret = 0, hlen;\n    size_t counter, out_len, len = derived_key_len;\n    unsigned char c[4];\n    unsigned char mac[EVP_MAX_MD_SIZE];\n    unsigned char *out = derived_key;\n    EVP_MD_CTX *ctx = NULL, *ctx_init = NULL;\n    if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN\n            || derived_key_len > SSKDF_MAX_INLEN\n            || derived_key_len == 0)\n        return 0;\n    hlen = EVP_MD_size(kdf_md);\n    if (hlen <= 0)\n        return 0;\n    out_len = (size_t)hlen;\n    ctx = EVP_MD_CTX_create();\n    ctx_init = EVP_MD_CTX_create();\n    if (ctx == NULL || ctx_init == NULL)\n        goto end;\n    if (!EVP_DigestInit(ctx_init, kdf_md))\n        goto end;\n    for (counter = 1;; counter++) {\n        c[0] = (unsigned char)((counter >> 24) & 0xff);\n        c[1] = (unsigned char)((counter >> 16) & 0xff);\n        c[2] = (unsigned char)((counter >> 8) & 0xff);\n        c[3] = (unsigned char)(counter & 0xff);\n        if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init)\n                && EVP_DigestUpdate(ctx, c, sizeof(c))\n                && EVP_DigestUpdate(ctx, z, z_len)\n                && EVP_DigestUpdate(ctx, info, info_len)))\n            goto end;\n        if (len >= out_len) {\n            if (!EVP_DigestFinal_ex(ctx, out, NULL))\n                goto end;\n            out += out_len;\n            len -= out_len;\n            if (len == 0)\n                break;\n        } else {\n            if (!EVP_DigestFinal_ex(ctx, mac, NULL))\n                goto end;\n            memcpy(out, mac, len);\n            break;\n        }\n    }\n    ret = 1;\nend:\n    EVP_MD_CTX_destroy(ctx);\n    EVP_MD_CTX_destroy(ctx_init);\n    OPENSSL_cleanse(mac, sizeof(mac));\n    return ret;\n}', 'int EVP_MD_size(const EVP_MD *md)\n{\n    if (!md) {\n        EVPerr(EVP_F_EVP_MD_SIZE, EVP_R_MESSAGE_DIGEST_IS_NULL);\n        return -1;\n    }\n    return md->md_size;\n}', 'EVP_MD_CTX *EVP_MD_CTX_new(void)\n{\n    return OPENSSL_zalloc(sizeof(EVP_MD_CTX));\n}', 'void *CRYPTO_zalloc(size_t num, const char *file, int line)\n{\n    void *ret = CRYPTO_malloc(num, file, line);\n    FAILTEST();\n    if (ret != NULL)\n        memset(ret, 0, num);\n    return ret;\n}', 'void *CRYPTO_malloc(size_t num, const char *file, int line)\n{\n    void *ret = NULL;\n    INCREMENT(malloc_count);\n    if (malloc_impl != NULL && malloc_impl != CRYPTO_malloc)\n        return malloc_impl(num, file, line);\n    if (num == 0)\n        return NULL;\n    FAILTEST();\n    if (allow_customize) {\n        allow_customize = 0;\n    }\n#ifndef OPENSSL_NO_CRYPTO_MDEBUG\n    if (call_malloc_debug) {\n        CRYPTO_mem_debug_malloc(NULL, num, 0, file, line);\n        ret = malloc(num);\n        CRYPTO_mem_debug_malloc(ret, num, 1, file, line);\n    } else {\n        ret = malloc(num);\n    }\n#else\n    (void)(file); (void)(line);\n    ret = malloc(num);\n#endif\n    return ret;\n}', 'void EVP_MD_CTX_free(EVP_MD_CTX *ctx)\n{\n    EVP_MD_CTX_reset(ctx);\n    OPENSSL_free(ctx);\n}', 'void CRYPTO_free(void *str, const char *file, int line)\n{\n    INCREMENT(free_count);\n    if (free_impl != NULL && free_impl != &CRYPTO_free) {\n        free_impl(str, file, line);\n        return;\n    }\n#ifndef OPENSSL_NO_CRYPTO_MDEBUG\n    if (call_malloc_debug) {\n        CRYPTO_mem_debug_free(str, 0, file, line);\n        free(str);\n        CRYPTO_mem_debug_free(str, 1, file, line);\n    } else {\n        free(str);\n    }\n#else\n    free(str);\n#endif\n}']