static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info,
                              X509_ALGOR **md_alg,
                              unsigned char **imprint, unsigned *imprint_len)
{
    TS_MSG_IMPRINT *msg_imprint = tst_info->msg_imprint;
    X509_ALGOR *md_alg_resp = msg_imprint->hash_algo;
    const EVP_MD *md;
    EVP_MD_CTX *md_ctx = NULL;
    unsigned char buffer[4096];
    int length;
    *md_alg = NULL;
    *imprint = NULL;
    if ((*md_alg = X509_ALGOR_dup(md_alg_resp)) == NULL)
        goto err;
    if ((md = EVP_get_digestbyobj((*md_alg)->algorithm)) == NULL) {
        TSerr(TS_F_TS_COMPUTE_IMPRINT, TS_R_UNSUPPORTED_MD_ALGORITHM);
        goto err;
    }
    length = EVP_MD_size(md);
    if (length < 0)
        goto err;
    *imprint_len = length;
    if ((*imprint = OPENSSL_malloc(*imprint_len)) == NULL) {
        TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    md_ctx = EVP_MD_CTX_new();
    if (md_ctx == NULL) {
        TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if (!EVP_DigestInit(md_ctx, md))
        goto err;
    while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0) {
        if (!EVP_DigestUpdate(md_ctx, buffer, length))
            goto err;
    }
    if (!EVP_DigestFinal(md_ctx, *imprint, NULL))
        goto err;
    EVP_MD_CTX_free(md_ctx);
    return 1;
 err:
    EVP_MD_CTX_free(md_ctx);
    X509_ALGOR_free(*md_alg);
    OPENSSL_free(*imprint);
    *imprint_len = 0;
    *imprint = 0;
    return 0;
}
['static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info,\n                              X509_ALGOR **md_alg,\n                              unsigned char **imprint, unsigned *imprint_len)\n{\n    TS_MSG_IMPRINT *msg_imprint = tst_info->msg_imprint;\n    X509_ALGOR *md_alg_resp = msg_imprint->hash_algo;\n    const EVP_MD *md;\n    EVP_MD_CTX *md_ctx = NULL;\n    unsigned char buffer[4096];\n    int length;\n    *md_alg = NULL;\n    *imprint = NULL;\n    if ((*md_alg = X509_ALGOR_dup(md_alg_resp)) == NULL)\n        goto err;\n    if ((md = EVP_get_digestbyobj((*md_alg)->algorithm)) == NULL) {\n        TSerr(TS_F_TS_COMPUTE_IMPRINT, TS_R_UNSUPPORTED_MD_ALGORITHM);\n        goto err;\n    }\n    length = EVP_MD_size(md);\n    if (length < 0)\n        goto err;\n    *imprint_len = length;\n    if ((*imprint = OPENSSL_malloc(*imprint_len)) == NULL) {\n        TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n    md_ctx = EVP_MD_CTX_new();\n    if (md_ctx == NULL) {\n        TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n    if (!EVP_DigestInit(md_ctx, md))\n        goto err;\n    while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0) {\n        if (!EVP_DigestUpdate(md_ctx, buffer, length))\n            goto err;\n    }\n    if (!EVP_DigestFinal(md_ctx, *imprint, NULL))\n        goto err;\n    EVP_MD_CTX_free(md_ctx);\n    return 1;\n err:\n    EVP_MD_CTX_free(md_ctx);\n    X509_ALGOR_free(*md_alg);\n    OPENSSL_free(*imprint);\n    *imprint_len = 0;\n    *imprint = 0;\n    return 0;\n}', 'IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)', 'void *ASN1_item_dup(const ASN1_ITEM *it, void *x)\n{\n    unsigned char *b = NULL;\n    const unsigned char *p;\n    long i;\n    void *ret;\n    if (x == NULL)\n        return (NULL);\n    i = ASN1_item_i2d(x, &b, it);\n    if (b == NULL) {\n        ASN1err(ASN1_F_ASN1_ITEM_DUP, ERR_R_MALLOC_FAILURE);\n        return (NULL);\n    }\n    p = b;\n    ret = ASN1_item_d2i(NULL, &p, i, it);\n    OPENSSL_free(b);\n    return (ret);\n}']