<commit_before>/*
 * %CopyrightBegin%
 *
 * Copyright Ericsson AB 2010-2018. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * %CopyrightEnd%
 */

#include "hash.h"
#include "digest.h"

#define MD5_CTX_LEN       (sizeof(MD5_CTX))
#define MD4_CTX_LEN       (sizeof(MD4_CTX))
#define RIPEMD160_CTX_LEN (sizeof(RIPEMD160_CTX))

#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
struct evp_md_ctx {
    EVP_MD_CTX* ctx;
};

/* Define resource types for OpenSSL context structures. */
static ErlNifResourceType* evp_md_ctx_rtype;

static void evp_md_ctx_dtor(ErlNifEnv* env, struct evp_md_ctx *ctx) {
    if (ctx == NULL)
        return;

    if (ctx->ctx)
        EVP_MD_CTX_free(ctx->ctx);
}
#endif

int init_hash_ctx(ErlNifEnv* env) {
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
    evp_md_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_MD_CTX",
                                               (ErlNifResourceDtor*) evp_md_ctx_dtor,
                                               ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
                                               NULL);
    if (evp_md_ctx_rtype == NULL) {
        PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'");
        return 0;
    }
#endif

    return 1;
}

ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Data) */
    struct digest_type_t *digp = NULL;
    const EVP_MD         *md;
    ErlNifBinary         data;
    ERL_NIF_TERM         ret;
    unsigned             ret_size;
    unsigned char        *outp;

    if (argc != 2)
        goto bad_arg;
    if ((digp = get_digest_type(argv[0])) == NULL)
        goto bad_arg;
    if (!enif_inspect_iolist_as_binary(env, argv[1], &data))
        goto bad_arg;

    if ((md = digp->md.p) == NULL)
        goto err;

    ret_size = (unsigned)EVP_MD_size(md);
    ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);

    if ((outp = enif_make_new_binary(env, ret_size, &ret)) == NULL)
        goto err;
    if (EVP_Digest(data.data, data.size, outp, &ret_size, md, NULL) != 1)
        goto err;

    ASSERT(ret_size == (unsigned)EVP_MD_size(md));

    CONSUME_REDS(env, data);
    return ret;

 bad_arg:
    return enif_make_badarg(env);

 err:
    return atom_notsup;
}

#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)

ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type) */
    struct digest_type_t *digp = NULL;
    struct evp_md_ctx    *ctx = NULL;
    ERL_NIF_TERM         ret;

    if (argc != 1)
        goto bad_arg;
    if ((digp = get_digest_type(argv[0])) == NULL)
        goto bad_arg;
    if (digp->md.p == NULL)
        goto err;

    if ((ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx))) == NULL)
        goto err;
    if ((ctx->ctx = EVP_MD_CTX_new()) == NULL)
        goto err;
    if (EVP_DigestInit(ctx->ctx, digp->md.p) != 1)
        goto err;

    ret = enif_make_resource(env, ctx);
    goto done;

 bad_arg:
    return enif_make_badarg(env);

 err:
    ret = atom_notsup;

 done:
    enif_release_resource(ctx);
    return ret;
}

ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data) */
    struct evp_md_ctx   *ctx, *new_ctx;
    ErlNifBinary data;
    ERL_NIF_TERM ret;

    if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx) ||
        !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
        return enif_make_badarg(env);
    }

    new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx));
    new_ctx->ctx = EVP_MD_CTX_new();
    if (!EVP_MD_CTX_copy(new_ctx->ctx, ctx->ctx) ||
        !EVP_DigestUpdate(new_ctx->ctx, data.data, data.size)) {
        enif_release_resource(new_ctx);
        return atom_notsup;
    }

    ret = enif_make_resource(env, new_ctx);
    enif_release_resource(new_ctx);
    CONSUME_REDS(env, data);
    return ret;
}

ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context) */
    struct evp_md_ctx *ctx;
    EVP_MD_CTX        *new_ctx;
    ERL_NIF_TERM  ret;
    unsigned      ret_size;

    if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) {<commit_msg>Revamp hash_update_nif()<commit_after>/*
 * %CopyrightBegin%
 *
 * Copyright Ericsson AB 2010-2018. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * %CopyrightEnd%
 */

#include "hash.h"
#include "digest.h"

#define MD5_CTX_LEN       (sizeof(MD5_CTX))
#define MD4_CTX_LEN       (sizeof(MD4_CTX))
#define RIPEMD160_CTX_LEN (sizeof(RIPEMD160_CTX))

#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
struct evp_md_ctx {
    EVP_MD_CTX* ctx;
};

/* Define resource types for OpenSSL context structures. */
static ErlNifResourceType* evp_md_ctx_rtype;

static void evp_md_ctx_dtor(ErlNifEnv* env, struct evp_md_ctx *ctx) {
    if (ctx == NULL)
        return;

    if (ctx->ctx)
        EVP_MD_CTX_free(ctx->ctx);
}
#endif

int init_hash_ctx(ErlNifEnv* env) {
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
    evp_md_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_MD_CTX",
                                               (ErlNifResourceDtor*) evp_md_ctx_dtor,
                                               ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
                                               NULL);
    if (evp_md_ctx_rtype == NULL) {
        PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'");
        return 0;
    }
#endif

    return 1;
}

ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Data) */
    struct digest_type_t *digp = NULL;
    const EVP_MD         *md;
    ErlNifBinary         data;
    ERL_NIF_TERM         ret;
    unsigned             ret_size;
    unsigned char        *outp;

    if (argc != 2)
        goto bad_arg;
    if ((digp = get_digest_type(argv[0])) == NULL)
        goto bad_arg;
    if (!enif_inspect_iolist_as_binary(env, argv[1], &data))
        goto bad_arg;

    if ((md = digp->md.p) == NULL)
        goto err;

    ret_size = (unsigned)EVP_MD_size(md);
    ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);

    if ((outp = enif_make_new_binary(env, ret_size, &ret)) == NULL)
        goto err;
    if (EVP_Digest(data.data, data.size, outp, &ret_size, md, NULL) != 1)
        goto err;

    ASSERT(ret_size == (unsigned)EVP_MD_size(md));

    CONSUME_REDS(env, data);
    return ret;

 bad_arg:
    return enif_make_badarg(env);

 err:
    return atom_notsup;
}

#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)

ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type) */
    struct digest_type_t *digp = NULL;
    struct evp_md_ctx    *ctx = NULL;
    ERL_NIF_TERM         ret;

    if (argc != 1)
        goto bad_arg;
    if ((digp = get_digest_type(argv[0])) == NULL)
        goto bad_arg;
    if (digp->md.p == NULL)
        goto err;

    if ((ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx))) == NULL)
        goto err;
    if ((ctx->ctx = EVP_MD_CTX_new()) == NULL)
        goto err;
    if (EVP_DigestInit(ctx->ctx, digp->md.p) != 1)
        goto err;

    ret = enif_make_resource(env, ctx);
    goto done;

 bad_arg:
    return enif_make_badarg(env);

 err:
    ret = atom_notsup;

 done:
    enif_release_resource(ctx);
    return ret;
}

ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data) */
    struct evp_md_ctx   *ctx, *new_ctx = NULL;
    ErlNifBinary data;
    ERL_NIF_TERM ret;

    if (argc != 2)
        goto bad_arg;
    if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx))
        goto bad_arg;
    if (!enif_inspect_iolist_as_binary(env, argv[1], &data))
        goto bad_arg;

    if ((new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx))) == NULL)
        goto err;
    if ((new_ctx->ctx = EVP_MD_CTX_new()) == NULL)
        goto err;
    if (EVP_MD_CTX_copy(new_ctx->ctx, ctx->ctx) != 1)
        goto err;
    if (EVP_DigestUpdate(new_ctx->ctx, data.data, data.size) != 1)
        goto err;

    ret = enif_make_resource(env, new_ctx);
    CONSUME_REDS(env, data);
    goto done;

 bad_arg:
    return enif_make_badarg(env);

 err:
    ret = atom_notsup;

 done:
    enif_release_resource(new_ctx);
    return ret;
}

ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context) */
    struct evp_md_ctx *ctx;
    EVP_MD_CTX        *new_ctx;
    ERL_NIF_TERM  ret;
    unsigned      ret_size;

    if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) {
{'fraction_non_alphanumeric': 0.1135640209467091, 'fraction_numerical': 0.009549235034397783, 'mean_word_length': 2.919517102615694, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5684358', 'n_tokens_mistral': 3744, 'n_tokens_neox': 3644, 'n_words': 819}